其中,部分注释是本人注的,大家讨论一下这个程序吧。 /* 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 #define START_LINE0 0xc0 #define DISPLAY_ON 0x3f #define DISPLAY_OFF 0x3e #define PARA1 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[1]; char Msk[16]; }; struct typFNT_ASC16 const ASC_16[] = { /* 显示为8*16 Curier 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[2]; char Msk[24]; }; 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[0]); for(k=0;k<len;k++) { if(c == ASC_16[k].Index[0] ) 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[k].Msk[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); if(uCol+j<64) ch_r=read_LCD(LEFT); else ch_r=read_LCD(RIGHT); ch_r&=0xf0; ch_w=ASC_16[k].Msk[ASC_CHR_WIDTH+j]&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[k].Msk[j]; 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[k].Msk[j]; ch_w=ASC_16[k].Msk[ASC_CHR_WIDTH+j]; 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[0]);k++) { if(hz[0] == GB_16[k].Index[0] && hz[1] == GB_16[k].Index[1]) break; } if(CurOffset==1) { for(j=0;j<ASC_HZ_WIDTH;j++) { SetPageCol(uPage,uCol+j); ch_w=GB_16[k].Msk[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); if(uCol+j<64) ch_r=read_LCD(LEFT); else ch_r=read_LCD(RIGHT); ch_r&=0xf0; ch_w=GB_16[k].Msk[ASC_HZ_WIDTH+j]&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[k].Msk[j]; 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[k].Msk[j]; ch_w=GB_16[k].Msk[ASC_HZ_WIDTH+j]; 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编辑过 | |||
__________________________ 天天进步,天天成长,天天快乐,天天健康!! zhaoxibo1980@126.com QQ:39787535 技术交流群:28625733 | |||
2006-11-10,09:15:05 |
|
【2楼】 mcuhost 波波 积分:156 派别: 等级:------ 来自:天津 | 是不是认为程序太简单了??~~~~ | ||
__________________________ 天天进步,天天成长,天天快乐,天天健康!! zhaoxibo1980@126.com QQ:39787535 技术交流群:28625733 | |||
2006-11-10,09:27:24 |
|
【3楼】 mcuhost 波波 积分:156 派别: 等级:------ 来自:天津 | 我疑惑!! | ||
__________________________ 天天进步,天天成长,天天快乐,天天健康!! zhaoxibo1980@126.com QQ:39787535 技术交流群:28625733 | |||
2006-11-10,10:22:20 |
|
【4楼】 armok 阿莫 积分:20336 派别: 等级:------ 来自:OurAVR.com 站长 | 要用到才会有人认真研究 .... | ||
__________________________ There's something good in this world. And it's worth fighting for …… 我的手机为:13433056000,如果本网站不正常,请用手机短信通知我。 我不用QQ,我用MSN:armokarmok@hotmail. 技术问题请在论坛发贴,否则我会忙不过来,谢谢。 | |||
2006-11-10,10:28:57 |
|
【5楼】 mcuhost 波波 积分:156 派别: 等级:------ 来自:天津 | armok兄言之有理 | ||
__________________________ 天天进步,天天成长,天天快乐,天天健康!! zhaoxibo1980@126.com QQ:39787535 技术交流群:28625733 | |||
2006-11-10,10:32:04 |
|
【6楼】 fbnfbn 积分:131 派别: 等级:------ 来自:广州番禺 | 请问这个液晶价格怎样,有没生产商或代理商的电话 谢谢! | ||
__________________________ 南 MSN: fbnfbnfbn@21cn.com | |||
2006-12-06,09:16:14 |
|
【7楼】 Gorgon Meducer 傻孩子 积分:693 派别: 等级:------ 来自:祖国的大西南 | 发现自己名字……路过…… | ||
2006-12-06,09:20:29 |
|
【8楼】 AVR-MEGA128 安步当车 积分:564 派别: 等级:------ 来自:http://www.ouravr.com/bbs/bbs_upload5678234990515/files_unde | ding 就一个字 | ||
__________________________ QQ:315716395 | |||
2006-12-06,09:30:50 |
|
【9楼】 fsclub 积分:1505 派别: 等级:------ 来自: | 刚刚以35米的价格买了个无字库的12864,正好是KS1008的,正好想配合GPS用来运动画轨迹.. 下来研究一下... | ||
__________________________ 欢迎光临俺的网站: http://www.mp3-cn.com | |||
2006-12-31,12:23:48 |
|
【10楼】 fsclub 积分:1505 派别: 等级:------ 来自: | //PORTA---数据口 PORTB----控制口 -------- 这个注释有问题吧? 我看PORTC才是控制口啊! | ||
__________________________ 欢迎光临俺的网站: http://www.mp3-cn.com | |||
2006-12-31,12:35:55 |
|
【11楼】 xuetwins 积分:3 派别: 等级:------ 来自: | to 楼主: 想在12864上做个反显示的程序,反显示的中文字数可以不限, 总是做不出,楼主能不能给个程序?? 或者给个思路也行 万分感谢!! 效果如下: | ||
2007-03-30,17:12:05 |
|
【12楼】 hxke 积分:22 派别: 等级:------ 来自: | to: xuetwins 写汉字之前把字模取反就ok了。。。。(加个~符号就搞定) | ||
2007-03-30,20:56:43 |
|
【13楼】 xuetwins 积分:3 派别: 等级:------ 来自: | 比如最上面楼主的程序 在哪里加~ ??? 麻烦你说清楚点,谢谢!!! | ||
2007-03-31,09:50:05 |
|
【14楼】 xuepeng2000 积分:164 派别: 等级:------ 来自: | if(uCol+j<64) ch_r=read_LCD(LEFT); else ch_r=read_LCD(RIGHT); ch_r=~ch_r; 再write就可以了 这里就可以 感觉写汉字和写字母的不应该分开,反正一个扫八列,一个扫十六列 用一个标志来做汉字和字母的判断, 那样就可以用一个函数写出来. | ||
2007-03-31,10:29:14 |
|
【15楼】 xuepeng2000 积分:164 派别: 等级:------ 来自: | 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时显示) * 出口参数:无 * 说明:操作失败原因是指定地址超出缓冲区范围。 ****************************************************************************/ void GUI_HLine(unsigned int x0, unsigned char y0, unsigned int x1, TCOLOR color) { unsigned char bak; 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时显示) * 出口参数: 无 * 说明:操作失败原因是指定地址超出缓冲区范围。 ***********************************************************************/ void GUI_RLine(unsigned int x0, unsigned char y0, unsigned char y1, TCOLOR color) { unsigned char bak; 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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 填充颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_RectangleFill(uint16 x0, uint8 y0, uint16 x1, uint8 y1, TCOLOR color) { uint32 i; /* 先找出矩形左上角与右下角的两个点,保存在(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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_Square(uint32 x0, uint32 y0, uint32 with, TCOLOR color) { 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时显示) * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_LineS(uint32 const *points, uint8 no, TCOLOR color) { uint32 x0, y0; uint32 x1, 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; } } #if GUI_CircleX_EN==1 /**************************************************************************** * 名称:GUI_Circle() * 功能:指定圆心位置及半径,画圆。 * 入口参数:x0 圆心的x坐标值 * y0 圆心的y坐标值 * r 圆的半径 * color 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_Circle(uint32 x0, uint32 y0, uint32 r, TCOLOR color) { int32 draw_x0, draw_y0; // 刽图点坐标变量 int32 draw_x1, draw_y1; int32 draw_x2, draw_y2; int32 draw_x3, draw_y3; int32 draw_x4, draw_y4; int32 draw_x5, draw_y5; int32 draw_x6, draw_y6; int32 draw_x7, draw_y7; int32 xx, yy; // 画圆控制变量 int32 di; // 决策变量 /* 参数过滤 */ 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 填充颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_CircleFill(uint32 x0, uint32 y0, uint32 r, TCOLOR color) { int32 draw_x0, draw_y0; // 刽图点坐标变量 int32 draw_x1, draw_y1; int32 draw_x2, draw_y2; int32 draw_x3, draw_y3; int32 draw_x4, draw_y4; int32 draw_x5, draw_y5; int32 draw_x6, draw_y6; int32 draw_x7, draw_y7; int32 fill_x0, fill_y0; // 填充所需的变量,使用垂直线填充 int32 fill_x1; int32 xx, yy; // 画圆控制变量 int32 di; // 决策变量 /* 参数过滤 */ 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 | ||
2007-03-31,10:49:28 |
|
【16楼】 xuepeng2000 积分:164 派别: 等级:------ 来自: | 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时显示) * 出口参数:无 * 说明:操作失败原因是指定地址超出缓冲区范围。 ****************************************************************************/ void GUI_HLine(unsigned int x0, unsigned char y0, unsigned int x1, TCOLOR color) { unsigned char bak; 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时显示) * 出口参数: 无 * 说明:操作失败原因是指定地址超出缓冲区范围。 ***********************************************************************/ void GUI_RLine(unsigned int x0, unsigned char y0, unsigned char y1, TCOLOR color) { unsigned char bak; 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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 填充颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_RectangleFill(uint16 x0, uint8 y0, uint16 x1, uint8 y1, TCOLOR color) { uint32 i; /* 先找出矩形左上角与右下角的两个点,保存在(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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_Square(uint32 x0, uint32 y0, uint32 with, TCOLOR color) { 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时显示) * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_LineS(uint32 const *points, uint8 no, TCOLOR color) { uint32 x0, y0; uint32 x1, 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; } } #if GUI_CircleX_EN==1 /**************************************************************************** * 名称:GUI_Circle() * 功能:指定圆心位置及半径,画圆。 * 入口参数:x0 圆心的x坐标值 * y0 圆心的y坐标值 * r 圆的半径 * color 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_Circle(uint32 x0, uint32 y0, uint32 r, TCOLOR color) { int32 draw_x0, draw_y0; // 刽图点坐标变量 int32 draw_x1, draw_y1; int32 draw_x2, draw_y2; int32 draw_x3, draw_y3; int32 draw_x4, draw_y4; int32 draw_x5, draw_y5; int32 draw_x6, draw_y6; int32 draw_x7, draw_y7; int32 xx, yy; // 画圆控制变量 int32 di; // 决策变量 /* 参数过滤 */ 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 填充颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_CircleFill(uint32 x0, uint32 y0, uint32 r, TCOLOR color) { int32 draw_x0, draw_y0; // 刽图点坐标变量 int32 draw_x1, draw_y1; int32 draw_x2, draw_y2; int32 draw_x3, draw_y3; int32 draw_x4, draw_y4; int32 draw_x5, draw_y5; int32 draw_x6, draw_y6; int32 draw_x7, draw_y7; int32 fill_x0, fill_y0; // 填充所需的变量,使用垂直线填充 int32 fill_x1; int32 xx, yy; // 画圆控制变量 int32 di; // 决策变量 /* 参数过滤 */ 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时显示) * 出口参数:无 * 说明:操作失败原因是指定地址超出缓冲区范围。 ****************************************************************************/ void GUI_HLine(unsigned int x0, unsigned char y0, unsigned int x1, TCOLOR color) { unsigned char bak; 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时显示) * 出口参数: 无 * 说明:操作失败原因是指定地址超出缓冲区范围。 ***********************************************************************/ void GUI_RLine(unsigned int x0, unsigned char y0, unsigned char y1, TCOLOR color) { unsigned char bak; 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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 填充颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_RectangleFill(uint16 x0, uint8 y0, uint16 x1, uint8 y1, TCOLOR color) { uint32 i; /* 先找出矩形左上角与右下角的两个点,保存在(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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_Square(uint32 x0, uint32 y0, uint32 with, TCOLOR color) { 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时显示) * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_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 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_LineS(uint32 const *points, uint8 no, TCOLOR color) { uint32 x0, y0; uint32 x1, 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; } } #if GUI_CircleX_EN==1 /**************************************************************************** * 名称:GUI_Circle() * 功能:指定圆心位置及半径,画圆。 * 入口参数:x0 圆心的x坐标值 * y0 圆心的y坐标值 * r 圆的半径 * color 显示颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_Circle(uint32 x0, uint32 y0, uint32 r, TCOLOR color) { int32 draw_x0, draw_y0; // 刽图点坐标变量 int32 draw_x1, draw_y1; int32 draw_x2, draw_y2; int32 draw_x3, draw_y3; int32 draw_x4, draw_y4; int32 draw_x5, draw_y5; int32 draw_x6, draw_y6; int32 draw_x7, draw_y7; int32 xx, yy; // 画圆控制变量 int32 di; // 决策变量 /* 参数过滤 */ 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 填充颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_CircleFill(uint32 x0, uint32 y0, uint32 r, TCOLOR color) { int32 draw_x0, draw_y0; // 刽图点坐标变量 int32 draw_x1, draw_y1; int32 draw_x2, draw_y2; int32 draw_x3, draw_y3; int32 draw_x4, draw_y4; int32 draw_x5, draw_y5; int32 draw_x6, draw_y6; int32 draw_x7, draw_y7; int32 fill_x0, fill_y0; // 填充所需的变量,使用垂直线填充 int32 fill_x1; int32 xx, yy; // 画圆控制变量 int32 di; // 决策变量 /* 参数过滤 */ 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 |
用户1477864 2011-4-6 14:41