强烈推荐一款LCM12864(KS0108)的完整应用程序,感觉和“傻孩子”的1206程序有异曲同工之
其中,部分注释是本人注的,大家讨论一下这个程序吧。/*
KS0108 128*64 LCD C语言驱动
参考ICCAVR资料和网上的资料改写
LCD引脚定义
1---GND
2---VCC
3---VLCD
4---D/I
5---R/W
6---E
7到14 D0-D7
15--CS1
16--CS2
17--RESET
18--VEE
19--SW
20--NC
*/
#include <iom16v.h>
#include <macros.h>
/* 当前行、列存储,行高16点,列宽8点 */
unsigned char CurOffset,CurRow,CurPage,CurCol;
/*常量定义*/
#define LCD_STATUS_BUSY 0x80
#defineSTART_LINE0 0xc0
#defineDISPLAY_ON 0x3f
#defineDISPLAY_OFF 0x3e
#definePARA1 0x40
//PORTA---数据口PORTB----控制口
#define LCD_DIR_PORT DDRA
#define LCD_IP_PORT PINA
#define LCD_OP_PORT PORTA
#define LCD_EN_PORT PORTC
#define LCD_CS2_PORT PORTC
#define LCD_CS1_PORT PORTC
#define LCD_RW_PORT PORTC
#define LCD_DI_PORT PORTC
#define LCD_DI_BIT BIT(7)//0x80
#define LCD_RW_BIT BIT(6)//0x40
#define LCD_EN_BIT BIT(5)//0x20
#define LCD_CS1_BIT BIT(4)//0x10
#define LCD_CS2_BIT BIT(3)//0x08
#define SET_LCD_E LCD_EN_PORT |= LCD_EN_BIT //LCD使能
#define CLEAR_LCD_E LCD_EN_PORT &= ~LCD_EN_BIT //LCD禁止
//以下可能出错,数据指令接口
#define SET_LCD_DATA LCD_DI_PORT |= LCD_DI_BIT //选择数据端口
#define SET_LCD_CMD LCD_DI_PORT &= ~LCD_DI_BIT //选择指令端口
#define SET_LCD_READ LCD_RW_PORT |= LCD_RW_BIT //读模式
#define SET_LCD_WRITE LCD_RW_PORT &= ~LCD_RW_BIT //写模式
#define SET_LCD_CS2 LCD_CS2_PORT |= LCD_CS2_BIT//右屏选择禁止
#define CLEAR_LCD_CS2 LCD_CS2_PORT &= ~LCD_CS2_BIT //右屏选择使能
#define SET_LCD_CS1 LCD_CS1_PORT |= LCD_CS1_BIT//左屏选择禁止
#define CLEAR_LCD_CS1 LCD_CS1_PORT &= ~LCD_CS1_BIT //左屏选择使能
#define LEFT 0
#define RIGHT 1
#define CMD 0
#define DATA 1
void LCD_BUSY(unsigned char lr) //判断忙标志。。
{
unsigned char status;
CLI();
if(lr==LEFT)
{
//选择左半屏。。
CLEAR_LCD_CS2; //cs2=0
SET_LCD_CS1; //cs1=1
}
else
{
//选择右半屏。。
SET_LCD_CS2; //cs2=1
CLEAR_LCD_CS1; //cs1=0
}
SET_LCD_CMD;//选择指令端口。。
LCD_DIR_PORT = 0x00;//数据口方向设置。。
LCD_OP_PORT = 0xff;//数据口输出高电平。。
SET_LCD_READ;//读模式。。
SET_LCD_E;//LCD使能。。
asm("nop"); asm("nop");
asm("nop"); asm("nop");
while((LCD_IP_PORT) & LCD_STATUS_BUSY)//判断LCD是否忙。。
{
CLEAR_LCD_E;//LCD禁止。。
asm("nop"); asm("nop");
asm("nop"); asm("nop");
SET_LCD_E;//LCD使能。。
asm("nop"); asm("nop");
asm("nop"); asm("nop");
}
CLEAR_LCD_E;
SET_LCD_WRITE;//写模式。。
LCD_OP_PORT = 0xff;//写入显示RAM
SEI();
}
void write_LCD(unsigned char lr,unsigned char cd,unsigned char data) /*写入指令或数据*/
{
CLI();
LCD_BUSY(lr);
if(cd==CMD) SET_LCD_CMD;
else SET_LCD_DATA;
SET_LCD_WRITE;
SET_LCD_E;
LCD_DIR_PORT = 0xff;
LCD_OP_PORT = data;
asm("nop"); asm("nop");
asm("nop"); asm("nop");
CLEAR_LCD_E;
LCD_OP_PORT = 0xff;
SEI();
}
unsigned char read_LCD(unsigned char lr) /*读显示数据 */
{
unsigned char data;
CLI();
LCD_BUSY(lr);
SET_LCD_DATA;
LCD_DIR_PORT = 0x00;
LCD_OP_PORT = 0xff;
SET_LCD_READ;
SET_LCD_E;
asm("nop"); asm("nop");
asm("nop"); asm("nop");
data=LCD_IP_PORT;
CLEAR_LCD_E;
SET_LCD_WRITE;
LCD_BUSY(lr);
SET_LCD_DATA;
LCD_DIR_PORT = 0x00;
LCD_OP_PORT = 0xff;
SET_LCD_READ;
SET_LCD_E;
asm("nop"); asm("nop");
asm("nop"); asm("nop");
data=LCD_IP_PORT;
CLEAR_LCD_E;
SET_LCD_WRITE;
SEI();
return data;
}
void set_start_line_L(unsigned char line) /*设置显示起始行*/ //0-63
{
write_LCD(LEFT,CMD,0xc0|line);
}
void set_start_line_R(unsigned char line) /*设置显示起始行*/ //0-63
{
write_LCD(RIGHT,CMD,0xc0|line);
}
void set_page_L(unsigned char page) /*设置X地址 设置页*///0-7
{
write_LCD(LEFT,CMD,0xb8|page);
}
void set_page_R(unsigned char page) /*设置X地址 设置页*/ //0-7
{
write_LCD(RIGHT,CMD,0xb8|page);
}
void set_col_addr_L(unsigned char col) /*设置Y地址*/ //0-63
{
write_LCD(LEFT,CMD,0x40|col);
}
void set_col_addr_R(unsigned char col) /*设置Y地址*/ //0-63
{
write_LCD(RIGHT,CMD,0x40|col);
}
void init_lcd(void) /*初始化函数*/
{
set_start_line_L(0); /*显示起始行为0*/
set_start_line_R(0); /*显示起始行为0*/
write_LCD(LEFT,CMD,DISPLAY_ON); /*开显示*/
write_LCD(RIGHT,CMD,DISPLAY_ON); /*开显示*/
}
void clr_lcd(void) /*清屏函数*/
{
unsigned char pages,i;
for(pages=0;pages<8;pages++)
{
set_page_L(pages);/* X 页地址 */
set_page_R(pages);/* X 页地址 */
for(i=0;i<64;i++)
{
set_col_addr_L(i);//Y
set_col_addr_R(i);//Y
write_LCD(LEFT,DATA,0x0);
write_LCD(RIGHT,DATA,0x0);
}
}
}
/*************************************/
/* 绘点函数 */
/*************************************/
void pixel(unsigned char xx,unsigned char yy,unsigned char flag)
{
unsigned int y,ch;
ch=yy%8;//余数
y=1;
for(;ch!=0;)
{
y=y*2;
ch--;
}
if(xx<64)
{
set_page_L(yy/8);
set_col_addr_L(xx);
ch=read_LCD(LEFT);
set_col_addr_L(xx);
if(flag)
write_LCD(LEFT,DATA,ch|y);
else
{
y=~y;
ch&=y;
write_LCD(LEFT,DATA,ch|y);
}
}
else
{
set_page_R(yy/8);
set_col_addr_R(xx-64);
ch=read_LCD(RIGHT);
set_col_addr_R(xx-64);
if(flag)
write_LCD(RIGHT,DATA,ch|y);
else
{
y=~y;
ch&=y;
write_LCD(RIGHT,DATA,ch|y);
}
}
}
//ASCII 字模宽度及高度
#define ASC_CHR_WIDTH 8
#define ASC_CHR_HEIGHT 12
typedef struct typFNT_ASC16 /* 汉字字模显示数据结构 */
{
char Index;
char Msk;
};
struct typFNT_ASC16 const ASC_16[] = { /* 显示为8*16Curier 10 常规*/
"1",0x00,0x00,0x08,0x08,0xFC,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x07,0x04,0x04,0x00,
"2",0x00,0x00,0x08,0x04,0x84,0x44,0x38,0x00,0x00,0x00,0x06,0x05,0x04,0x04,0x04,0x00,
"3",0x00,0x00,0x08,0x04,0x44,0x44,0xB8,0x00,0x00,0x00,0x02,0x04,0x04,0x04,0x03,0x00,
"4",0x00,0x00,0x80,0x60,0x18,0xFC,0x00,0x00,0x00,0x00,0x01,0x01,0x05,0x07,0x05,0x00,
"5",0x00,0x00,0x7C,0x44,0x44,0x44,0x84,0x00,0x00,0x00,0x02,0x04,0x04,0x04,0x03,0x00,
"6",0x00,0x00,0xF0,0x48,0x44,0x44,0x80,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x00,
"7",0x00,0x00,0x0C,0x04,0x84,0x64,0x1C,0x00,0x00,0x00,0x00,0x06,0x01,0x00,0x00,0x00,
"8",0x00,0x00,0xB8,0x44,0x44,0x44,0xB8,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x00,
"9",0x00,0x00,0x38,0x44,0x44,0x44,0xF8,0x00,0x00,0x00,0x00,0x04,0x04,0x02,0x01,0x00,
"0",0x00,0x00,0xF8,0x04,0x04,0x04,0xF8,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x00,
".",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00,0x00,
":",0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00,
" ",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
"(",0x00,0x00,0x00,0xE0,0x18,0x04,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x10,0x00,0x00,
")",0x00,0x00,0x00,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x00,0x10,0x0C,0x03,0x00,0x00,
};
#define ASC_HZ_WIDTH 12
//#define ASC_HZ_HEIGHT 12
typedef struct typFNT_GB16 /*12*16 汉字字模显示数据结构 */
{
char Index;
char Msk;
};
struct typFNT_GB16 const GB_16[] = { /* 宋体 9小五 显示为12*16 */
"液",0x19,0xE2,0x14,0x42,0xF2,0x2E,0x72,0x8F,0xAA,0x7A,0x02,0x00,0x01,0x07,0x00,0x00,0x07,0x04,0x04,0x02,0x01,0x02,0x04,0x00,
"晶",0x00,0xC0,0x40,0x5F,0xD5,0x15,0xD5,0x55,0x5F,0x40,0xC0,0x00,0x00,0x07,0x05,0x05,0x07,0x00,0x07,0x05,0x05,0x05,0x07,0x00,
"显",0x00,0x40,0x9F,0x15,0xD5,0x15,0xD5,0x15,0x1F,0xC0,0x00,0x00,0x04,0x04,0x05,0x04,0x07,0x04,0x07,0x06,0x05,0x04,0x04,0x00,
"示",0x10,0x12,0x92,0x52,0x12,0xF2,0x12,0x12,0x53,0x92,0x10,0x00,0x02,0x01,0x00,0x04,0x04,0x07,0x00,0x00,0x00,0x00,0x03,0x00,
"的",0xFC,0x44,0x46,0x45,0xFC,0x10,0x2C,0xC7,0x04,0x04,0xFC,0x00,0x07,0x02,0x02,0x02,0x07,0x00,0x00,0x04,0x04,0x04,0x03,0x00,
"第",0x04,0xEA,0xAB,0xAE,0xAA,0xFC,0xAA,0xAB,0xAE,0xBA,0x82,0x00,0x04,0x04,0x02,0x01,0x00,0x07,0x00,0x02,0x02,0x02,0x01,0x00,
"一",0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
"行",0x48,0x24,0xF3,0x08,0x09,0x09,0x09,0x09,0xF9,0x09,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x04,0x04,0x04,0x07,0x00,0x00,0x00,
"二",0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,
"三",0x00,0x02,0x22,0x22,0x22,0x22,0x22,0x22,0x23,0x02,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,
"四",0x00,0xFF,0x81,0x41,0x3F,0x01,0x01,0xFF,0x81,0x81,0xFF,0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x07,0x00,
"五",0x00,0x11,0x11,0x91,0x7F,0x11,0x11,0x11,0xF1,0x01,0x00,0x00,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x00,
};
unsigned char GetPage(void) /*得到当前页*/
{
return CurPage;
}
unsigned char GetCol(void) /*得到当前列*/
{
return CurCol;
}
void SetPageCol(unsigned char upage, unsigned char ucol) /* 设置液晶的页和列 */
{
CurPage = upage;
CurCol = ucol;
if(ucol<64)
{
set_page_L(upage);
set_col_addr_L(ucol);
}
else
{
set_page_R(upage);
set_col_addr_R(ucol-64);
}
}
/* 设置当前显示的页和列 */
void SetRowCol(unsigned char urow, unsigned char ucol)
{
unsigned char page;
CurRow = urow;
CurCol = ucol;
switch(urow)
{
case 1:
page=0;
CurOffset=1;
break;
case 2:
page=1;
CurOffset=2;
break;
case 3:
page=3;
CurOffset=1;
break;
case 4:
page=4;
CurOffset=2;
break;
case 5:
page=6;
CurOffset=1;
break;
}
SetPageCol(page,ucol);
}
void disp_char(unsigned char c)
{
unsigned char k,j,uPage,uCol,ch_r,ch_w;
unsigned char width;
unsigned char len;
uPage = GetPage();
uCol = GetCol();
len=sizeof(ASC_16)/sizeof(ASC_16);
for(k=0;k<len;k++)
{
if(c == ASC_16.Index ) break;
}
if(k<len)
{
if(c=='-'||c==':')
width=ASC_CHR_WIDTH-2;
else if(c=='|')
width=ASC_HZ_WIDTH-ASC_CHR_WIDTH;
else
width=ASC_CHR_WIDTH;
if(CurOffset==1) //下半部是写半个字节
{
for(j=0;j<width;j++)
{
SetPageCol(uPage,uCol+j);
ch_w=ASC_16.Msk;
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage+1,uCol);
for(j=0;j<width;j++)
{
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) ch_r=read_LCD(LEFT);
else ch_r=read_LCD(RIGHT);
ch_r&=0xf0;
ch_w=ASC_16.Msk&0x0f;
ch_w|=ch_r;
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
}
else //上半部是写半个字节
{
for(j=0;j<width;j++)
{
SetPageCol(uPage,uCol+j);
if(uCol+j<64) ch_r=read_LCD(LEFT);
else ch_r=read_LCD(RIGHT);
ch_r&=0x0f;
ch_w=ASC_16.Msk;
ch_w=ch_w<<4;
ch_w|=ch_r;
SetPageCol(uPage,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage+1,uCol);
for(j=0;j<width;j++)
{
SetPageCol(uPage+1,uCol+j);
ch_r=ASC_16.Msk;
ch_w=ASC_16.Msk;
ch_r=ch_r>>4;
ch_w=ch_w<<4;
ch_w|=ch_r;
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
}
}
SetPageCol(uPage,uCol+width);
}
void disp_hz(unsigned char const *hz)
{
unsigned char k,j,uPage,uCol,ch_r,ch_w;
uPage = GetPage();
uCol = GetCol();
for(k=0;k<sizeof(GB_16)/sizeof(GB_16);k++)
{
if(hz == GB_16.Index && hz == GB_16.Index)
break;
}
if(CurOffset==1)
{
for(j=0;j<ASC_HZ_WIDTH;j++)
{
SetPageCol(uPage,uCol+j);
ch_w=GB_16.Msk;
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage+1,uCol);
for(j=0;j<ASC_HZ_WIDTH;j++)
{
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) ch_r=read_LCD(LEFT);
else ch_r=read_LCD(RIGHT);
ch_r&=0xf0;
ch_w=GB_16.Msk&0x0f;
ch_w|=ch_r;
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage,uCol+ASC_HZ_WIDTH);
}
else //汉字上半部是写半个字节
{
for(j=0;j<ASC_HZ_WIDTH;j++)
{
SetPageCol(uPage,uCol+j);
if(uCol+j<64) ch_r=read_LCD(LEFT);
else ch_r=read_LCD(RIGHT);
ch_r&=0x0f;
ch_w=GB_16.Msk;
ch_w=ch_w<<4;
ch_w|=ch_r;
SetPageCol(uPage,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage+1,uCol);
for(j=0;j<ASC_HZ_WIDTH;j++)
{
SetPageCol(uPage+1,uCol+j);
ch_r=GB_16.Msk;
ch_w=GB_16.Msk;
ch_r=ch_r>>4;
ch_w=ch_w<<4;
ch_w|=ch_r;
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage,uCol+ASC_HZ_WIDTH);
}
}
void disp_str(unsigned char const *p)
{
unsigned char i=0;
while(p>0)
{
if(p < 128)
{ /* ASCII */
disp_char(p);
}
else
{ /* 中文 */
disp_hz(&p);
i++;
}
i++;
}
}
void main()
{
unsigned char i;
DDRC=0xff;
init_lcd();
clr_lcd();
SetRowCol(1,0);
disp_str("液晶显示的第一行1234");
SetRowCol(2,0);
disp_str("液晶显示的第二行2345");
SetRowCol(3,0);
disp_str("液晶显示的第三行3456");
SetRowCol(4,0);
disp_str("液晶显示的第四行5678");
SetRowCol(5,0);
disp_str("液晶显示的第五行6789");
for(i=0;i<64;i++) pixel(127,i,1);
for(i=0;i<64;i++) pixel(0,i,1);
for(i=0;i<128;i++) pixel(i,0,1);
for(i=0;i<128;i++) pixel(i,63,1);
while(1);
}
-----此内容被mcuhost于2006-11-10,09:31:24编辑过 是不是认为程序太简单了??~~~~ 我疑惑!! 要用到才会有人认真研究 .... armok兄言之有理 请问这个液晶价格怎样,有没生产商或代理商的电话
谢谢! 发现自己名字……路过…… ding 就一个字 刚刚以35米的价格买了个无字库的12864,正好是KS1008的,正好想配合GPS用来运动画轨迹..
下来研究一下... //PORTA---数据口PORTB----控制口
--------
这个注释有问题吧?
我看PORTC才是控制口啊! to 楼主:
想在12864上做个反显示的程序,反显示的中文字数可以不限, 总是做不出,楼主能不能给个程序?? 或者给个思路也行
万分感谢!!
效果如下:
http://cache.amobbs.com/bbs_upload782111/files_6/armok01148622.jpg to: xuetwins
写汉字之前把字模取反就ok了。。。。(加个~符号就搞定)
:)./emotion/em078.gif 比如最上面楼主的程序
在哪里加~ ???
麻烦你说清楚点,谢谢!!! if(uCol+j<64) ch_r=read_LCD(LEFT);
else ch_r=read_LCD(RIGHT);
ch_r=~ch_r;
再write就可以了
这里就可以
感觉写汉字和写字母的不应该分开,反正一个扫八列,一个扫十六列
用一个标志来做汉字和字母的判断,
那样就可以用一个函数写出来. 我把GUI贴上来
/****************************************************************************************
* 文件名:GUI.C
* 功能:GUI基本绘图函数。进行基本绘图运算,并调用相应的刷新程序更新LCD显示。
* 作者:黄绍斌
* 修改:冯建辉
* 日期:2006.09.13
* 备注:图形操作层,进行各种图形运算操作。
****************************************************************************************/
#include "gui.h"
#include <math.h>
/****************************************************************************
* 名称:GUI_HLine()
* 功能:画水平线。
* 入口参数:x0 水平线起点所在列的位置
* y0 水平线起点所在行的位置
* x1 水平线终点所在列的位置
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
* 说明:操作失败原因是指定地址超出缓冲区范围。
****************************************************************************/
voidGUI_HLine(unsigned int x0, unsigned char y0, unsigned int x1, TCOLOR color)
{
unsigned charbak;
if(x0>x1) // 对x0、x1大小进行排列,以便画图
{
bak = x1;
x1 = x0;
x0 = bak;
}
do
{
GUI_Point(x0, y0, color); // 逐点显示,描出垂直线
x0++;
}
while(x1>=x0);
}
/***********************************************************************
* 名称:GUI_RLine()
* 功能:画竖直线。根据硬件特点,实现加速。
* 入口参数:x0 垂直线起点所在列的位置
* y0 垂直线起点所在行的位置
* y1 垂直线终点所在行的位置
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数: 无
* 说明:操作失败原因是指定地址超出缓冲区范围。
***********************************************************************/
voidGUI_RLine(unsigned int x0, unsigned char y0, unsigned char y1, TCOLOR color)
{
unsigned charbak;
if(y0>y1) // 对y0、y1大小进行排列,以便画图
{
bak = y1;
y1 = y0;
y0 = bak;
}
do
{
GUI_Point(x0, y0, color); // 逐点显示,描出垂直线
y0++;
}
while(y1>=y0);
}
/****************************************************************************
* 名称:GUI_Rectangle()
* 功能:画矩形。
* 入口参数:x0 矩形左上角的x坐标值
* y0 矩形左上角的y坐标值
* x1 矩形右下角的x坐标值
* y1 矩形右下角的y坐标值
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Rectangle(uint16 x0, uint8 y0, uint16 x1, uint8 y1, TCOLOR color)
{
GUI_HLine(x0, y0, x1, color);
GUI_HLine(x0, y1, x1, color);
GUI_RLine(x0, y0, y1, color);
GUI_RLine(x1, y0, y1, color);
}
/****************************************************************************
* 名称:GUI_RectangleFill()
* 功能:填充矩形。画一个填充的矩形,填充色与边框色一样。
* 入口参数:x0 矩形左上角的x坐标值
* y0 矩形左上角的y坐标值
* x1 矩形右下角的x坐标值
* y1 矩形右下角的y坐标值
* color 填充颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_RectangleFill(uint16 x0, uint8 y0, uint16 x1, uint8 y1, TCOLOR color)
{
uint32i;
/* 先找出矩形左上角与右下角的两个点,保存在(x0,y0),(x1,y1) */
if(x0>x1) // 若x0>x1,则x0与x1交换
{
i = x0;
x0 = x1;
x1 = i;
}
if(y0>y1) // 若y0>y1,则y0与y1交换
{
i = y0;
y0 = y1;
y1 = i;
}
/* 判断是否只是直线 */
if(y0==y1)
{
GUI_HLine(x0, y0, x1, color);
return;
}
if(x0==x1)
{
GUI_RLine(x0, y0, y1, color);
return;
}
while(y0<=y1)
{
GUI_HLine(x0, y0, x1, color); // 当前画水平线
y0++; // 下一行
}
}
/****************************************************************************
* 名称:GUI_Square()
* 功能:画正方形。
* 入口参数:x0 正方形左上角的x坐标值
* y0 正方形左上角的y坐标值
* with 正方形的边长
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Square(uint32 x0, uint32 y0, uint32with, TCOLORcolor)
{
if(with==0)
return;
if( (x0+with) > GUI_LCM_XMAX )
return;
if( (y0+with) > GUI_LCM_YMAX )
return;
GUI_Rectangle(x0, y0, x0+with, y0+with, color);
}
/****************************************************************************
* 名称:GUI_Line()
* 功能:画任意两点之间的直线。
* 入口参数:x0 直线起点的x坐标值
* y0 直线起点的y坐标值
* x1 直线终点的x坐标值
* y1 直线终点的y坐标值
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Line(uint32 x0, uint32 y0, uint32 x1, uint32 y1, TCOLOR color)
{
int32 dx; // 直线x轴差值变量
int32 dy; // 直线y轴差值变量
int8 dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向
int8 dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向
int32 dx_x2; // dx*2值变量,用于加快运算速度
int32 dy_x2; // dy*2值变量,用于加快运算速度
int32 di; // 决策变量
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
/* 判断增长方向,或是否为水平线、垂直线、点 */
if(dx>0) // 判断x轴方向
{
dx_sym = 1; // dx>0,设置dx_sym=1
}
else
{
if(dx<0)
{
dx_sym = -1; // dx<0,设置dx_sym=-1
}
else
{// dx==0,画垂直线,或一点
GUI_RLine(x0, y0, y1, color);
return;
}
}
if(dy>0) // 判断y轴方向
{
dy_sym = 1; // dy>0,设置dy_sym=1
}
else
{
if(dy<0)
{
dy_sym = -1; // dy<0,设置dy_sym=-1
}
else
{// dy==0,画水平线,或一点
GUI_HLine(x0, y0, x1, color);
return;
}
}
/* 将dx、dy取绝对值 */
dx = dx_sym * dx;
dy = dy_sym * dy;
/* 计算2倍的dx及dy值 */
dx_x2 = dx*2;
dy_x2 = dy*2;
/* 使用Bresenham法进行画直线 */
if(dx>=dy) // 对于dx>=dy,则使用x轴为基准
{
di = dy_x2 - dx;
while(x0!=x1)
{
GUI_Point(x0, y0, color);
x0 += dx_sym;
if(di<0)
{
di += dy_x2; // 计算出下一步的决策值
}
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
GUI_Point(x0, y0, color); // 显示最后一点
}
else // 对于dx<dy,则使用y轴为基准
{
di = dx_x2 - dy;
while(y0!=y1)
{
GUI_Point(x0, y0, color);
y0 += dy_sym;
if(di<0)
{
di += dx_x2;
}
else
{
di += dx_x2 - dy_x2;
x0 += dx_sym;
}
}
GUI_Point(x0, y0, color); // 显示最后一点
}
}
#if GUI_LineWith_EN==1
/****************************************************************************
* 名称:GUI_LineWith()
* 功能:画任意两点之间的直线,并且可设置线的宽度。
* 入口参数:x0 直线起点的x坐标值
* y0 直线起点的y坐标值
* x1 直线终点的x坐标值
* y1 直线终点的y坐标值
* with 线宽(0-50)
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_LineWith(uint32 x0, uint32 y0, uint32 x1, uint32 y1, uint8 with, TCOLOR color)
{
int32 dx; // 直线x轴差值变量
int32 dy; // 直线y轴差值变量
int8 dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向
int8 dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向
int32 dx_x2; // dx*2值变量,用于加快运算速度
int32 dy_x2; // dy*2值变量,用于加快运算速度
int32 di; // 决策变量
int32 wx, wy; // 线宽变量
int32 draw_a, draw_b;
/* 参数过滤 */
if(with==0)
return;
if(with>50)
with = 50;
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
wx = with/2;
wy = with-wx-1;
/* 判断增长方向,或是否为水平线、垂直线、点 */
if(dx>0) // 判断x轴方向
{
dx_sym = 1; // dx>0,设置dx_sym=1
}
else
{
if(dx<0)
{
dx_sym = -1; // dx<0,设置dx_sym=-1
}
else
{/* dx==0,画垂直线,或一点 */
wx = x0-wx;
if(wx<0)
wx = 0;
wy = x0+wy;
while(1)
{
x0 = wx;
GUI_RLine(x0, y0, y1, color);
if(wx>=wy)
break;
wx++;
}
return;
}
}
if(dy>0) // 判断y轴方向
{
dy_sym = 1; // dy>0,设置dy_sym=1
}
else
{
if(dy<0)
{
dy_sym = -1; // dy<0,设置dy_sym=-1
}
else
{/* dy==0,画水平线,或一点 */
wx = y0-wx;
if(wx<0) wx = 0;
wy = y0+wy;
while(1)
{
y0 = wx;
GUI_HLine(x0, y0, x1, color);
if(wx>=wy)
break;
wx++;
}
return;
}
}
/* 将dx、dy取绝对值 */
dx = dx_sym * dx;
dy = dy_sym * dy;
/* 计算2倍的dx及dy值 */
dx_x2 = dx*2;
dy_x2 = dy*2;
/* 使用Bresenham法进行画直线 */
if(dx>=dy) // 对于dx>=dy,则使用x轴为基准
{
di = dy_x2 - dx;
while(x0!=x1)
{/* x轴向增长,则宽度在y方向,即画垂直线 */
draw_a = y0-wx;
if(draw_a<0) draw_a = 0;
draw_b = y0+wy;
GUI_RLine(x0, draw_a, draw_b, color);
x0 += dx_sym;
if(di<0)
{
di += dy_x2; // 计算出下一步的决策值
}
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
draw_a = y0-wx;
if(draw_a<0)
draw_a = 0;
draw_b = y0+wy;
GUI_RLine(x0, draw_a, draw_b, color);
}
else // 对于dx<dy,则使用y轴为基准
{
di = dx_x2 - dy;
while(y0!=y1)
{/* y轴向增长,则宽度在x方向,即画水平线 */
draw_a = x0-wx;
if(draw_a<0)
draw_a = 0;
draw_b = x0+wy;
GUI_HLine(draw_a, y0, draw_b, color);
y0 += dy_sym;
if(di<0)
{
di += dx_x2;
}
else
{
di += dx_x2 - dy_x2;
x0 += dx_sym;
}
}
draw_a = x0-wx;
if(draw_a<0)
draw_a = 0;
draw_b = x0+wy;
GUI_HLine(draw_a, y0, draw_b, color);
}
}
#endif
/****************************************************************************
* 名称:GUI_LineS()
* 功能:多个点之间的连续连线。从第一点连到第二点,再连到第三点...
* 入口参数:points 多个点坐标数据的指针,数据排列为(x0,y0)、(x1,y1)、(x2,y2)...
* no 点数目,至少要大于1
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_LineS(uint32 const *points, uint8 no, TCOLOR color)
{
uint32x0, y0;
uint32x1, y1;
uint8 i;
/* 入口参数过滤 */
if(0==no)
return;
if(1==no) // 单点
{
x0 = *points++;
y0 = *points;
GUI_Point(x0, y0, color);
}
/* 画多条线条 */
x0 = *points++; // 取出第一点坐标值,作为原起点坐标值
y0 = *points++;
for(i=1; i<no; i++)
{
x1 = *points++; // 取出下一点坐标值
y1 = *points++;
GUI_Line(x0, y0, x1, y1, color);
x0 = x1; // 更新原起点坐标
y0 = y1;
}
}
#ifGUI_CircleX_EN==1
/****************************************************************************
* 名称:GUI_Circle()
* 功能:指定圆心位置及半径,画圆。
* 入口参数:x0 圆心的x坐标值
* y0 圆心的y坐标值
* r 圆的半径
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Circle(uint32 x0, uint32 y0, uint32 r, TCOLOR color)
{
int32draw_x0, draw_y0; // 刽图点坐标变量
int32draw_x1, draw_y1;
int32draw_x2, draw_y2;
int32draw_x3, draw_y3;
int32draw_x4, draw_y4;
int32draw_x5, draw_y5;
int32draw_x6, draw_y6;
int32draw_x7, draw_y7;
int32xx, yy; // 画圆控制变量
int32di; // 决策变量
/* 参数过滤 */
if(0==r)
return;
/* 计算出8个特殊点(0、45、90、135、180、225、270度),进行显示 */
draw_x0 = draw_x1 = x0;
draw_y0 = draw_y1 = y0 + r;
if(draw_y0<GUI_LCM_YMAX)
GUI_Point(draw_x0, draw_y0, color); // 90度
draw_x2 = draw_x3 = x0;
draw_y2 = draw_y3 = y0 - r;
if(draw_y2>=0)
GUI_Point(draw_x2, draw_y2, color); // 270度
draw_x4 = draw_x6 = x0 + r;
draw_y4 = draw_y6 = y0;
if(draw_x4<GUI_LCM_XMAX)
GUI_Point(draw_x4, draw_y4, color); // 0度
draw_x5 = draw_x7 = x0 - r;
draw_y5 = draw_y7 = y0;
if(draw_x5>=0)
GUI_Point(draw_x5, draw_y5, color); // 180度
if(1==r)
return; // 若半径为1,则已圆画完
/* 使用Bresenham法进行画圆 */
di = 3 - 2*r; // 初始化决策变量
xx = 0;
yy = r;
while(xx<yy)
{
if(di<0)
{
di += 4*xx + 6;
}
else
{
di += 4*(xx - yy) + 10;
yy--;
draw_y0--;
draw_y1--;
draw_y2++;
draw_y3++;
draw_x4--;
draw_x5++;
draw_x6--;
draw_x7++;
}
xx++;
draw_x0++;
draw_x1--;
draw_x2++;
draw_x3--;
draw_y4++;
draw_y5++;
draw_y6--;
draw_y7--;
/* 要判断当前点是否在有效范围内 */
if( (draw_x0<=GUI_LCM_XMAX)&&(draw_y0>=0) )
{
GUI_Point(draw_x0, draw_y0, color);
}
if( (draw_x1>=0)&&(draw_y1>=0) )
{
GUI_Point(draw_x1, draw_y1, color);
}
if( (draw_x2<=GUI_LCM_XMAX)&&(draw_y2<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x2, draw_y2, color);
}
if( (draw_x3>=0)&&(draw_y3<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x3, draw_y3, color);
}
if( (draw_x4<=GUI_LCM_XMAX)&&(draw_y4>=0) )
{
GUI_Point(draw_x4, draw_y4, color);
}
if( (draw_x5>=0)&&(draw_y5>=0) )
{
GUI_Point(draw_x5, draw_y5, color);
}
if( (draw_x6<=GUI_LCM_XMAX)&&(draw_y6<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x6, draw_y6, color);
}
if( (draw_x7>=0)&&(draw_y7<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x7, draw_y7, color);
}
}
}
/****************************************************************************
* 名称:GUI_CircleFill()
* 功能:指定圆心位置及半径,画圆并填充,填充色与边框色一样。
* 入口参数:x0 圆心的x坐标值
* y0 圆心的y坐标值
* r 圆的半径
* color 填充颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_CircleFill(uint32 x0, uint32 y0, uint32 r, TCOLOR color)
{
int32draw_x0, draw_y0; // 刽图点坐标变量
int32draw_x1, draw_y1;
int32draw_x2, draw_y2;
int32draw_x3, draw_y3;
int32draw_x4, draw_y4;
int32draw_x5, draw_y5;
int32draw_x6, draw_y6;
int32draw_x7, draw_y7;
int32fill_x0, fill_y0; // 填充所需的变量,使用垂直线填充
int32fill_x1;
int32xx, yy; // 画圆控制变量
int32di; // 决策变量
/* 参数过滤 */
if(0==r)
return;
/* 计算出4个特殊点(0、90、180、270度),进行显示 */
draw_x0 = draw_x1 = x0;
draw_y0 = draw_y1 = y0 + r;
if(draw_y0<GUI_LCM_YMAX)
{
GUI_Point(draw_x0, draw_y0, color); // 90度
}
draw_x2 = draw_x3 = x0;
draw_y2 = draw_y3 = y0 - r;
if(draw_y2>=0)
{
GUI_Point(draw_x2, draw_y2, color); // 270度
}
draw_x4 = draw_x6 = x0 + r;
draw_y4 = draw_y6 = y0;
if(draw_x4<GUI_LCM_XMAX)
{
GUI_Point(draw_x4, draw_y4, color); // 0度
fill_x1 = draw_x4;
}
else
{
fill_x1 = GUI_LCM_XMAX;
}
fill_y0 = y0; // 设置填充线条起始点fill_x0
fill_x0 = x0 - r; // 设置填充线条结束点fill_y1
if(fill_x0<0)
fill_x0 = 0;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
draw_x5 = draw_x7 = x0 - r;
draw_y5 = draw_y7 = y0;
if(draw_x5>=0)
{
GUI_Point(draw_x5, draw_y5, color); // 180度
}
if(1==r)
return;
/* 使用Bresenham法进行画圆 */
di = 3 - 2*r; // 初始化决策变量
xx = 0;
yy = r;
while(xx<yy)
{
if(di<0)
{
di += 4*xx + 6;
}
else
{
di += 4*(xx - yy) + 10;
yy--;
draw_y0--;
draw_y1--;
draw_y2++;
draw_y3++;
draw_x4--;
draw_x5++;
draw_x6--;
draw_x7++;
}
xx++;
draw_x0++;
draw_x1--;
draw_x2++;
draw_x3--;
draw_y4++;
draw_y5++;
draw_y6--;
draw_y7--;
/* 要判断当前点是否在有效范围内 */
if( (draw_x0<=GUI_LCM_XMAX)&&(draw_y0>=0) )
{
GUI_Point(draw_x0, draw_y0, color);
}
if( (draw_x1>=0)&&(draw_y1>=0) )
{
GUI_Point(draw_x1, draw_y1, color);
}
/* 第二点水直线填充(下半圆的点) */
if(draw_x1>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x1;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y1;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x1;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
if( (draw_x2<=GUI_LCM_XMAX)&&(draw_y2<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x2, draw_y2, color);
}
if( (draw_x3>=0)&&(draw_y3<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x3, draw_y3, color);
}
/* 第四点垂直线填充(上半圆的点) */
if(draw_x3>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x3;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y3;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x3;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
if( (draw_x4<=GUI_LCM_XMAX)&&(draw_y4>=0) )
{
GUI_Point(draw_x4, draw_y4, color);
}
if( (draw_x5>=0)&&(draw_y5>=0) )
{
GUI_Point(draw_x5, draw_y5, color);
}
/* 第六点垂直线填充(上半圆的点) */
if(draw_x5>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x5;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y5;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x5;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
if( (draw_x6<=GUI_LCM_XMAX)&&(draw_y6<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x6, draw_y6, color);
}
if( (draw_x7>=0)&&(draw_y7<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x7, draw_y7, color);
}
/* 第八点垂直线填充(上半圆的点) */
if(draw_x7>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x7;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y7;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x7;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
}
}
#endif 我把GUI贴上来
/****************************************************************************************
* 文件名:GUI.C
* 功能:GUI基本绘图函数。进行基本绘图运算,并调用相应的刷新程序更新LCD显示。
* 作者:黄绍斌
* 修改:冯建辉
* 日期:2006.09.13
* 备注:图形操作层,进行各种图形运算操作。
****************************************************************************************/
#include "gui.h"
#include <math.h>
/****************************************************************************
* 名称:GUI_HLine()
* 功能:画水平线。
* 入口参数:x0 水平线起点所在列的位置
* y0 水平线起点所在行的位置
* x1 水平线终点所在列的位置
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
* 说明:操作失败原因是指定地址超出缓冲区范围。
****************************************************************************/
voidGUI_HLine(unsigned int x0, unsigned char y0, unsigned int x1, TCOLOR color)
{
unsigned charbak;
if(x0>x1) // 对x0、x1大小进行排列,以便画图
{
bak = x1;
x1 = x0;
x0 = bak;
}
do
{
GUI_Point(x0, y0, color); // 逐点显示,描出垂直线
x0++;
}
while(x1>=x0);
}
/***********************************************************************
* 名称:GUI_RLine()
* 功能:画竖直线。根据硬件特点,实现加速。
* 入口参数:x0 垂直线起点所在列的位置
* y0 垂直线起点所在行的位置
* y1 垂直线终点所在行的位置
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数: 无
* 说明:操作失败原因是指定地址超出缓冲区范围。
***********************************************************************/
voidGUI_RLine(unsigned int x0, unsigned char y0, unsigned char y1, TCOLOR color)
{
unsigned charbak;
if(y0>y1) // 对y0、y1大小进行排列,以便画图
{
bak = y1;
y1 = y0;
y0 = bak;
}
do
{
GUI_Point(x0, y0, color); // 逐点显示,描出垂直线
y0++;
}
while(y1>=y0);
}
/****************************************************************************
* 名称:GUI_Rectangle()
* 功能:画矩形。
* 入口参数:x0 矩形左上角的x坐标值
* y0 矩形左上角的y坐标值
* x1 矩形右下角的x坐标值
* y1 矩形右下角的y坐标值
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Rectangle(uint16 x0, uint8 y0, uint16 x1, uint8 y1, TCOLOR color)
{
GUI_HLine(x0, y0, x1, color);
GUI_HLine(x0, y1, x1, color);
GUI_RLine(x0, y0, y1, color);
GUI_RLine(x1, y0, y1, color);
}
/****************************************************************************
* 名称:GUI_RectangleFill()
* 功能:填充矩形。画一个填充的矩形,填充色与边框色一样。
* 入口参数:x0 矩形左上角的x坐标值
* y0 矩形左上角的y坐标值
* x1 矩形右下角的x坐标值
* y1 矩形右下角的y坐标值
* color 填充颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_RectangleFill(uint16 x0, uint8 y0, uint16 x1, uint8 y1, TCOLOR color)
{
uint32i;
/* 先找出矩形左上角与右下角的两个点,保存在(x0,y0),(x1,y1) */
if(x0>x1) // 若x0>x1,则x0与x1交换
{
i = x0;
x0 = x1;
x1 = i;
}
if(y0>y1) // 若y0>y1,则y0与y1交换
{
i = y0;
y0 = y1;
y1 = i;
}
/* 判断是否只是直线 */
if(y0==y1)
{
GUI_HLine(x0, y0, x1, color);
return;
}
if(x0==x1)
{
GUI_RLine(x0, y0, y1, color);
return;
}
while(y0<=y1)
{
GUI_HLine(x0, y0, x1, color); // 当前画水平线
y0++; // 下一行
}
}
/****************************************************************************
* 名称:GUI_Square()
* 功能:画正方形。
* 入口参数:x0 正方形左上角的x坐标值
* y0 正方形左上角的y坐标值
* with 正方形的边长
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Square(uint32 x0, uint32 y0, uint32with, TCOLORcolor)
{
if(with==0)
return;
if( (x0+with) > GUI_LCM_XMAX )
return;
if( (y0+with) > GUI_LCM_YMAX )
return;
GUI_Rectangle(x0, y0, x0+with, y0+with, color);
}
/****************************************************************************
* 名称:GUI_Line()
* 功能:画任意两点之间的直线。
* 入口参数:x0 直线起点的x坐标值
* y0 直线起点的y坐标值
* x1 直线终点的x坐标值
* y1 直线终点的y坐标值
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Line(uint32 x0, uint32 y0, uint32 x1, uint32 y1, TCOLOR color)
{
int32 dx; // 直线x轴差值变量
int32 dy; // 直线y轴差值变量
int8 dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向
int8 dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向
int32 dx_x2; // dx*2值变量,用于加快运算速度
int32 dy_x2; // dy*2值变量,用于加快运算速度
int32 di; // 决策变量
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
/* 判断增长方向,或是否为水平线、垂直线、点 */
if(dx>0) // 判断x轴方向
{
dx_sym = 1; // dx>0,设置dx_sym=1
}
else
{
if(dx<0)
{
dx_sym = -1; // dx<0,设置dx_sym=-1
}
else
{// dx==0,画垂直线,或一点
GUI_RLine(x0, y0, y1, color);
return;
}
}
if(dy>0) // 判断y轴方向
{
dy_sym = 1; // dy>0,设置dy_sym=1
}
else
{
if(dy<0)
{
dy_sym = -1; // dy<0,设置dy_sym=-1
}
else
{// dy==0,画水平线,或一点
GUI_HLine(x0, y0, x1, color);
return;
}
}
/* 将dx、dy取绝对值 */
dx = dx_sym * dx;
dy = dy_sym * dy;
/* 计算2倍的dx及dy值 */
dx_x2 = dx*2;
dy_x2 = dy*2;
/* 使用Bresenham法进行画直线 */
if(dx>=dy) // 对于dx>=dy,则使用x轴为基准
{
di = dy_x2 - dx;
while(x0!=x1)
{
GUI_Point(x0, y0, color);
x0 += dx_sym;
if(di<0)
{
di += dy_x2; // 计算出下一步的决策值
}
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
GUI_Point(x0, y0, color); // 显示最后一点
}
else // 对于dx<dy,则使用y轴为基准
{
di = dx_x2 - dy;
while(y0!=y1)
{
GUI_Point(x0, y0, color);
y0 += dy_sym;
if(di<0)
{
di += dx_x2;
}
else
{
di += dx_x2 - dy_x2;
x0 += dx_sym;
}
}
GUI_Point(x0, y0, color); // 显示最后一点
}
}
#if GUI_LineWith_EN==1
/****************************************************************************
* 名称:GUI_LineWith()
* 功能:画任意两点之间的直线,并且可设置线的宽度。
* 入口参数:x0 直线起点的x坐标值
* y0 直线起点的y坐标值
* x1 直线终点的x坐标值
* y1 直线终点的y坐标值
* with 线宽(0-50)
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_LineWith(uint32 x0, uint32 y0, uint32 x1, uint32 y1, uint8 with, TCOLOR color)
{
int32 dx; // 直线x轴差值变量
int32 dy; // 直线y轴差值变量
int8 dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向
int8 dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向
int32 dx_x2; // dx*2值变量,用于加快运算速度
int32 dy_x2; // dy*2值变量,用于加快运算速度
int32 di; // 决策变量
int32 wx, wy; // 线宽变量
int32 draw_a, draw_b;
/* 参数过滤 */
if(with==0)
return;
if(with>50)
with = 50;
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
wx = with/2;
wy = with-wx-1;
/* 判断增长方向,或是否为水平线、垂直线、点 */
if(dx>0) // 判断x轴方向
{
dx_sym = 1; // dx>0,设置dx_sym=1
}
else
{
if(dx<0)
{
dx_sym = -1; // dx<0,设置dx_sym=-1
}
else
{/* dx==0,画垂直线,或一点 */
wx = x0-wx;
if(wx<0)
wx = 0;
wy = x0+wy;
while(1)
{
x0 = wx;
GUI_RLine(x0, y0, y1, color);
if(wx>=wy)
break;
wx++;
}
return;
}
}
if(dy>0) // 判断y轴方向
{
dy_sym = 1; // dy>0,设置dy_sym=1
}
else
{
if(dy<0)
{
dy_sym = -1; // dy<0,设置dy_sym=-1
}
else
{/* dy==0,画水平线,或一点 */
wx = y0-wx;
if(wx<0) wx = 0;
wy = y0+wy;
while(1)
{
y0 = wx;
GUI_HLine(x0, y0, x1, color);
if(wx>=wy)
break;
wx++;
}
return;
}
}
/* 将dx、dy取绝对值 */
dx = dx_sym * dx;
dy = dy_sym * dy;
/* 计算2倍的dx及dy值 */
dx_x2 = dx*2;
dy_x2 = dy*2;
/* 使用Bresenham法进行画直线 */
if(dx>=dy) // 对于dx>=dy,则使用x轴为基准
{
di = dy_x2 - dx;
while(x0!=x1)
{/* x轴向增长,则宽度在y方向,即画垂直线 */
draw_a = y0-wx;
if(draw_a<0) draw_a = 0;
draw_b = y0+wy;
GUI_RLine(x0, draw_a, draw_b, color);
x0 += dx_sym;
if(di<0)
{
di += dy_x2; // 计算出下一步的决策值
}
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
draw_a = y0-wx;
if(draw_a<0)
draw_a = 0;
draw_b = y0+wy;
GUI_RLine(x0, draw_a, draw_b, color);
}
else // 对于dx<dy,则使用y轴为基准
{
di = dx_x2 - dy;
while(y0!=y1)
{/* y轴向增长,则宽度在x方向,即画水平线 */
draw_a = x0-wx;
if(draw_a<0)
draw_a = 0;
draw_b = x0+wy;
GUI_HLine(draw_a, y0, draw_b, color);
y0 += dy_sym;
if(di<0)
{
di += dx_x2;
}
else
{
di += dx_x2 - dy_x2;
x0 += dx_sym;
}
}
draw_a = x0-wx;
if(draw_a<0)
draw_a = 0;
draw_b = x0+wy;
GUI_HLine(draw_a, y0, draw_b, color);
}
}
#endif
/****************************************************************************
* 名称:GUI_LineS()
* 功能:多个点之间的连续连线。从第一点连到第二点,再连到第三点...
* 入口参数:points 多个点坐标数据的指针,数据排列为(x0,y0)、(x1,y1)、(x2,y2)...
* no 点数目,至少要大于1
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_LineS(uint32 const *points, uint8 no, TCOLOR color)
{
uint32x0, y0;
uint32x1, y1;
uint8 i;
/* 入口参数过滤 */
if(0==no)
return;
if(1==no) // 单点
{
x0 = *points++;
y0 = *points;
GUI_Point(x0, y0, color);
}
/* 画多条线条 */
x0 = *points++; // 取出第一点坐标值,作为原起点坐标值
y0 = *points++;
for(i=1; i<no; i++)
{
x1 = *points++; // 取出下一点坐标值
y1 = *points++;
GUI_Line(x0, y0, x1, y1, color);
x0 = x1; // 更新原起点坐标
y0 = y1;
}
}
#ifGUI_CircleX_EN==1
/****************************************************************************
* 名称:GUI_Circle()
* 功能:指定圆心位置及半径,画圆。
* 入口参数:x0 圆心的x坐标值
* y0 圆心的y坐标值
* r 圆的半径
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_Circle(uint32 x0, uint32 y0, uint32 r, TCOLOR color)
{
int32draw_x0, draw_y0; // 刽图点坐标变量
int32draw_x1, draw_y1;
int32draw_x2, draw_y2;
int32draw_x3, draw_y3;
int32draw_x4, draw_y4;
int32draw_x5, draw_y5;
int32draw_x6, draw_y6;
int32draw_x7, draw_y7;
int32xx, yy; // 画圆控制变量
int32di; // 决策变量
/* 参数过滤 */
if(0==r)
return;
/* 计算出8个特殊点(0、45、90、135、180、225、270度),进行显示 */
draw_x0 = draw_x1 = x0;
draw_y0 = draw_y1 = y0 + r;
if(draw_y0<GUI_LCM_YMAX)
GUI_Point(draw_x0, draw_y0, color); // 90度
draw_x2 = draw_x3 = x0;
draw_y2 = draw_y3 = y0 - r;
if(draw_y2>=0)
GUI_Point(draw_x2, draw_y2, color); // 270度
draw_x4 = draw_x6 = x0 + r;
draw_y4 = draw_y6 = y0;
if(draw_x4<GUI_LCM_XMAX)
GUI_Point(draw_x4, draw_y4, color); // 0度
draw_x5 = draw_x7 = x0 - r;
draw_y5 = draw_y7 = y0;
if(draw_x5>=0)
GUI_Point(draw_x5, draw_y5, color); // 180度
if(1==r)
return; // 若半径为1,则已圆画完
/* 使用Bresenham法进行画圆 */
di = 3 - 2*r; // 初始化决策变量
xx = 0;
yy = r;
while(xx<yy)
{
if(di<0)
{
di += 4*xx + 6;
}
else
{
di += 4*(xx - yy) + 10;
yy--;
draw_y0--;
draw_y1--;
draw_y2++;
draw_y3++;
draw_x4--;
draw_x5++;
draw_x6--;
draw_x7++;
}
xx++;
draw_x0++;
draw_x1--;
draw_x2++;
draw_x3--;
draw_y4++;
draw_y5++;
draw_y6--;
draw_y7--;
/* 要判断当前点是否在有效范围内 */
if( (draw_x0<=GUI_LCM_XMAX)&&(draw_y0>=0) )
{
GUI_Point(draw_x0, draw_y0, color);
}
if( (draw_x1>=0)&&(draw_y1>=0) )
{
GUI_Point(draw_x1, draw_y1, color);
}
if( (draw_x2<=GUI_LCM_XMAX)&&(draw_y2<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x2, draw_y2, color);
}
if( (draw_x3>=0)&&(draw_y3<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x3, draw_y3, color);
}
if( (draw_x4<=GUI_LCM_XMAX)&&(draw_y4>=0) )
{
GUI_Point(draw_x4, draw_y4, color);
}
if( (draw_x5>=0)&&(draw_y5>=0) )
{
GUI_Point(draw_x5, draw_y5, color);
}
if( (draw_x6<=GUI_LCM_XMAX)&&(draw_y6<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x6, draw_y6, color);
}
if( (draw_x7>=0)&&(draw_y7<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x7, draw_y7, color);
}
}
}
/****************************************************************************
* 名称:GUI_CircleFill()
* 功能:指定圆心位置及半径,画圆并填充,填充色与边框色一样。
* 入口参数:x0 圆心的x坐标值
* y0 圆心的y坐标值
* r 圆的半径
* color 填充颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
voidGUI_CircleFill(uint32 x0, uint32 y0, uint32 r, TCOLOR color)
{
int32draw_x0, draw_y0; // 刽图点坐标变量
int32draw_x1, draw_y1;
int32draw_x2, draw_y2;
int32draw_x3, draw_y3;
int32draw_x4, draw_y4;
int32draw_x5, draw_y5;
int32draw_x6, draw_y6;
int32draw_x7, draw_y7;
int32fill_x0, fill_y0; // 填充所需的变量,使用垂直线填充
int32fill_x1;
int32xx, yy; // 画圆控制变量
int32di; // 决策变量
/* 参数过滤 */
if(0==r)
return;
/* 计算出4个特殊点(0、90、180、270度),进行显示 */
draw_x0 = draw_x1 = x0;
draw_y0 = draw_y1 = y0 + r;
if(draw_y0<GUI_LCM_YMAX)
{
GUI_Point(draw_x0, draw_y0, color); // 90度
}
draw_x2 = draw_x3 = x0;
draw_y2 = draw_y3 = y0 - r;
if(draw_y2>=0)
{
GUI_Point(draw_x2, draw_y2, color); // 270度
}
draw_x4 = draw_x6 = x0 + r;
draw_y4 = draw_y6 = y0;
if(draw_x4<GUI_LCM_XMAX)
{
GUI_Point(draw_x4, draw_y4, color); // 0度
fill_x1 = draw_x4;
}
else
{
fill_x1 = GUI_LCM_XMAX;
}
fill_y0 = y0; // 设置填充线条起始点fill_x0
fill_x0 = x0 - r; // 设置填充线条结束点fill_y1
if(fill_x0<0)
fill_x0 = 0;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
draw_x5 = draw_x7 = x0 - r;
draw_y5 = draw_y7 = y0;
if(draw_x5>=0)
{
GUI_Point(draw_x5, draw_y5, color); // 180度
}
if(1==r)
return;
/* 使用Bresenham法进行画圆 */
di = 3 - 2*r; // 初始化决策变量
xx = 0;
yy = r;
while(xx<yy)
{
if(di<0)
{
di += 4*xx + 6;
}
else
{
di += 4*(xx - yy) + 10;
yy--;
draw_y0--;
draw_y1--;
draw_y2++;
draw_y3++;
draw_x4--;
draw_x5++;
draw_x6--;
draw_x7++;
}
xx++;
draw_x0++;
draw_x1--;
draw_x2++;
draw_x3--;
draw_y4++;
draw_y5++;
draw_y6--;
draw_y7--;
/* 要判断当前点是否在有效范围内 */
if( (draw_x0<=GUI_LCM_XMAX)&&(draw_y0>=0) )
{
GUI_Point(draw_x0, draw_y0, color);
}
if( (draw_x1>=0)&&(draw_y1>=0) )
{
GUI_Point(draw_x1, draw_y1, color);
}
/* 第二点水直线填充(下半圆的点) */
if(draw_x1>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x1;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y1;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x1;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
if( (draw_x2<=GUI_LCM_XMAX)&&(draw_y2<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x2, draw_y2, color);
}
if( (draw_x3>=0)&&(draw_y3<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x3, draw_y3, color);
}
/* 第四点垂直线填充(上半圆的点) */
if(draw_x3>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x3;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y3;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x3;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
if( (draw_x4<=GUI_LCM_XMAX)&&(draw_y4>=0) )
{
GUI_Point(draw_x4, draw_y4, color);
}
if( (draw_x5>=0)&&(draw_y5>=0) )
{
GUI_Point(draw_x5, draw_y5, color);
}
/* 第六点垂直线填充(上半圆的点) */
if(draw_x5>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x5;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y5;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x5;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
if( (draw_x6<=GUI_LCM_XMAX)&&(draw_y6<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x6, draw_y6, color);
}
if( (draw_x7>=0)&&(draw_y7<=GUI_LCM_YMAX) )
{
GUI_Point(draw_x7, draw_y7, color);
}
/* 第八点垂直线填充(上半圆的点) */
if(draw_x7>=0)
{/* 设置填充线条起始点fill_x0 */
fill_x0 = draw_x7;
/* 设置填充线条起始点fill_y0 */
fill_y0 = draw_y7;
if(fill_y0>GUI_LCM_YMAX)
fill_y0 = GUI_LCM_YMAX;
if(fill_y0<0)
fill_y0 = 0;
/* 设置填充线条结束点fill_x1 */
fill_x1 = x0*2 - draw_x7;
if(fill_x1>GUI_LCM_XMAX)
fill_x1 = GUI_LCM_XMAX;
GUI_HLine(fill_x0, fill_y0, fill_x1, color);
}
}
}
#endif 辛苦了,谢谢啦! 请问你对数字取模用的什么取模软件?取模方式是什么? 请问你的是用ICC编译器吗?
转GCC怎么转呢? 呵呵 收下了哈!不错的哈! JH 在多个画椭圆就好了 嘿嘿 小弟有个TS12864A-2,管脚定义似乎跟楼主的一样,好像也没有字库的,
买的时候没看清楚,用了90大洋,我亏啊!收藏楼主的程序了! MARK 也顶一个 好东西收下了 标记~~~~~~~~~ 顶!做记号 一定有用~~!! 顶!做记号 版主我想问一下关于IO口的设置问题的,我现在用飞思卡尔单片机不能显示,不知道为什么 留着侯用,谢谢 路过,好东西要珍藏 9楼在哪里买的啊,这么便宜? ddddddddddddddddddd 哈哈不错 点击此处打开 ourdev_458799.jpg(文件大小:2.25M,只有400K以内的图片才能直接显示) (原文件名:12864.jpg)
这就是效果吗?
点击此处下载 ourdev_458800.rar(文件大小:78K) (原文件名:12864.rar)
protues 仿真效果 楼主用的什么字模提取软件?我试了好几个都不对。 mark GUI写得不错,收藏了. MARK mark!收藏 收下,研究研究! 收下先! 这个是用在哪个MCU上的?我自己写了两个ARM的,STM32和LM3S,都挺好用的。 这样也能加精?那我上次写的1500行的液晶驱动要是放上来,那不是也能拿精! 不是做广告,我也是刚开始用这个屏,昨晚才仿真了一下
http://www.gptlcm.cn/CN/list.asp?proname=OCM12864-3
这个网站的屏提供了详细的驱动代码。挺好用的。
ISIS 7 Professional里也有这个屏 好贴,谢谢了 强贴留名中 我用了几种字模软件,字体都不如C51的字模III好看,可惜到期了,给自动加了一个横线。大家有没有发现其他比较好的字模软件啊? 还有那个GUI是用在KS0108上面的吗? 好贴,研究研究! 研究 在我的显示模块上,画线正常,字符不正常呀,楼上的同志有调通的吗,给指点一下吧,谢谢了! 支持一下 收藏GUI程序。 mark,留用! 没有字库,刷屏慢点 mark 顶 先顶一个···话说我的lcd还不知道是不是好的呢··· 顶 mark 那个GUI的程序不知道有人用过没有呢?看上去挺牛的 mark 学习 正好刚收了几片白菜KS0108 12864,有空试试看…… mark MARK GUI mark mark too 无图无真相 mark mark 汗,我之前也自己写了个驱动的,原来大家都有了,拿来参考参考,改进改进~ mark MARK 紧跟在后马克 mark mark mark 学习了,我的屏是MD12864A,驱动器好像就是这一个 mark 又是个古董贴啊 mark mark!~~ mark 我看了这个帖子 ,很好 ,比较通用 但是,其中有些地方不明白,希望有人给程序注释一下啊,
if(CurOffset==1) //下半部是写半个字节
{
for(j=0;j<width;j++)
{
SetPageCol(uPage,uCol+j);
ch_w=ASC_16.Msk;
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage+1,uCol);
for(j=0;j<width;j++)
{
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) ch_r=read_LCD(LEFT);
else ch_r=read_LCD(RIGHT);
ch_r&=0xf0;
ch_w=ASC_16.Msk&0x0f;
ch_w|=ch_r;
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
}
else //上半部是写半个字节
{
for(j=0;j<width;j++)
{
SetPageCol(uPage,uCol+j);
if(uCol+j<64) ch_r=read_LCD(LEFT);
else ch_r=read_LCD(RIGHT);
ch_r&=0x0f;
ch_w=ASC_16.Msk;
ch_w=ch_w<<4;
ch_w|=ch_r;
SetPageCol(uPage,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
SetPageCol(uPage+1,uCol);
for(j=0;j<width;j++)
{
SetPageCol(uPage+1,uCol+j);
ch_r=ASC_16.Msk;
ch_w=ASC_16.Msk;
ch_r=ch_r>>4;
ch_w=ch_w<<4;
ch_w|=ch_r;
SetPageCol(uPage+1,uCol+j);
if(uCol+j<64) write_LCD(LEFT,DATA,ch_w);
else write_LCD(RIGHT,DATA,ch_w);
}
}
}
SetPageCol(uPage,uCol+width);
} 好帖啊,顶之~ 谢谢分享~ mark GOOD mark mark mark mark mark mark mark GOOD!必须MARK!
页:
[1]
2