1、12864绘图程序大集合/*/程序说明:本程序为12864(st7920)驱动程序,只实现了最简单的显示功能/端口设置:RS、RW、EN分别为P0口的0、1、2,数据口为P2口用取模软件取的图形或汉字必须是逐行取的,因为本函数是在液晶上逐行打点的/*/#include#include /内含-NOP-函数#include /内含rand()函数#define uchar unsigned char#define uint unsigned int/*宏定义所需指令#define BASIC_SET 0x30#define EXTEND_SET 0x34#define DRAW_ON 0x36#
2、define DRAW_OFF 0x34/*端口定义sbit LCD_RS = P00;sbit LCD_RW = P01;sbit LCD_EN = P02;/*变量定义/uchar dis110;/*短延时void delay(uint k) uint i; uchar j; for(i = 0; i k ;i +) for(j = 0; j 10 ;j +);/*ms级延时函数/*void delay_1ms(uint x) uint i,j; for(j = 0;j x; j+) for(i = 0;i 110; i+); */*12864写指令函数void write_com(uch
3、ar cmd) LCD_RS = 0; LCD_RW = 0; P2 = cmd; delay(5); LCD_EN = 1; delay(5); LCD_EN = 0;/*12864写数据函数void write_dat(uchar dat) LCD_RS = 1; LCD_RW = 0; P2 = dat; delay(5); LCD_EN = 1; delay(5); LCD_EN = 0;/*从LCD中读数据uchar read_dat(void) uchar temp; P2 = 0XFF; /释放数据线 LCD_RS = 1; /数据 LCD_RW = 1; / 读模式 LCD_E
4、N = 1; /E为高电平进行读数据或指令 delay(1); temp = P2; LCD_EN = 0; return temp; /*/设置光标(地址)函数/参数说明:x-为行号,y为列号/*void set_cursor(unsigned char x, unsigned char y) unsigned char i; switch(x) /确定行号 case 0x00: i=0x80; break; /第一行 case 0x01: i=0x90; break; /第二行 case 0x02: i=0x88; break; /第三行 case 0x03: i=0x98; break;
5、 /第四行 default : break; i = y+i; /确定列号 write_com(i);/*/显示字符函数/*void display_char(unsigned char Alphabet) write_dat(Alphabet); /写入需要显示字符的显示码/*/指定位置显示字符串函数/参数说明:x为行号,y为列号/*void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet) unsigned char i=0; set_cursor(x,y); /设置显示的起始地址 while(A
6、lphabeti!=0) write_dat(Alphabeti); /写入需要显示字符的显示码 i+; /*以下为GDRAM绘图部分*/*绘图显示的清屏函数(因清屏指令在画图时不能用)-注意!void gui_clear() uchar i , j , k; write_com(EXTEND_SET);/扩展指令集,8位数据传输 write_com(DRAW_OFF);/绘图显示关闭 for(i = 0; i 2; i +)/分上下两屏写 for(j = 0; j 32; j +) write_com(0x80 + j);/写y坐标 delay(1); if(i = 0) /写x坐标 wri
7、te_com(0x80); delay(1); else /写下半屏 write_com(0x88); delay(1); for(k = 0; k 16; k +)/写一整行数据 write_dat(0x00);/写高字节 write_dat(0x00);/写低字节 delay(1); write_com(DRAW_ON);/打开绘图显示 write_com(BASIC_SET);/打开基本指令集/*/*有反白显示功能的打点函数*/参数:color=1,该点填充1;color=0,该点填充白色0;/*void GUI_Point(unsigned char x,unsigned char y
8、,unsigned char color) unsigned char x_Dyte,x_byte; /定义列地址的字节位,及在字节中的哪1位 unsigned char y_Dyte,y_byte; /定义为上下两个屏(取值为0,1),行地址(取值为031) unsigned char GDRAM_hbit,GDRAM_lbit; write_com(0x36); /扩展指令命令 /*X,Y坐标互换,即普通的X,Y坐标*/ x_Dyte=x/16; /计算在16个字节中的哪一个 x_byte=x&0x0f; /计算在该字节中的哪一位 y_Dyte=y/32; /0为上半屏,1为下半屏 y_b
9、yte=y&0x1f; /计算在031当中的哪一行 write_com(0x80+y_byte); /设定行地址(y坐标),即是垂直地址 write_com(0x80+x_Dyte+8*y_Dyte); /设定列地址(x坐标),并通过8*y_Dyte选定上下屏,即是水平地址 read_dat(); /预读取数据 GDRAM_hbit= read_dat(); /读取当前显示高8位数据 GDRAM_lbit= read_dat(); /读取当前显示低8位数据 delay(1); write_com(0x80+y_byte); /设定行地址(y坐标) write_com(0x80+x_Dyte+8
10、*y_Dyte); /设定列地址(x坐标),并通过8*y_Dyte选定上下屏 delay(1); if(x_byte8) /判断其在高8位,还是在低8位 if(color=1) write_dat(GDRAM_hbit|(0x01(7-x_byte); /置位GDRAM区高8位数据中相应的点 else write_dat(GDRAM_hbit&(0x01(7-x_byte); /清除GDRAM区高8位数据中相应的点 write_dat(GDRAM_lbit); /显示GDRAM区低8位数据 else write_dat(GDRAM_hbit); if(color=1) write_dat(GD
11、RAM_lbit|(0x01(15-x_byte); /置位GDRAM区高8位数据中相应的点 else write_dat(GDRAM_lbit&(0x01(15-x_byte);/清除GDRAM区高8位数据中相应的点 write_com(0x30); /恢复到基本指令集/*(给定坐标并打点的)任意位置打点函数void lcd_set_dot(uchar x,uchar y) uchar x_byte,x_bit;/确定在坐标的那一字节哪一位 uchar y_ping , y_bit;/确定在坐标的哪一屏哪一行 uchar tmph , tmpl;/定义两个临时变量,用于存放读出来的数据 wr
12、ite_com(EXTEND_SET);/扩展指令集 write_com(DRAW_OFF);/绘图显示关闭 x_byte = x / 16;/算出在哪一字节,注意一个地址是16位的 x_bit = x % 16;/& 0x0f;/算出在哪一位 y_ping = y / 32;/确定在上半屏还是下半屏,0代表上半屏,1代表下半屏 y_bit = y % 32;/& 0x1f;/确定在第几行 write_com(0X80 + y_bit);/先写垂直地址(最高位必须) write_com(0x80 + x_byte + 8 * y_ping);/水平坐标,下半屏坐标起始地址为0x88,(+8*y
13、_ping)就是用来确定上半屏还是下半屏 read_dat();/预读取数据 tmph = read_dat();/读取当前显示高8位数据 tmpl = read_dat();/读取当前显示低8位数据 delay(1); write_com(0x80 + y_bit);/读操作会改变AC,所以重新设置一下 write_com(0x80 + x_byte + 8 * y_ping); delay(1); if(x_bit 8) write_dat(tmph | (0x01 (7 - x_bit);/写高字节,因为坐标是从左向右的,GDRAM高位在昨,低位在右 write_dat(tmpl);/原
14、低位数据送回 else write_dat(tmph);/原高位数据送回 write_dat(tmpl | (0x01 x1) bak = x1; x1 = x0; x0 = bak; do lcd_set_dot(x0 , y);/从左到右逐点显示 x0 +; while(x1 = x0);/*画竖直线函数*/x为起始点和终点的水平坐标,y0、y1为垂直坐标*/*/void gui_rline(uchar x, uchar y0, uchar y1) uchar bak;/用于对两个数互换的中间变量,使y1为大值 if(y0 y1) bak = y1; y1 = y0; y0 = bak;
15、do lcd_set_dot(x , y0);/从上到下逐点显示 y0 +; while(y1 = y0);/*任意两点间画直线*/x0、y0为起始点坐标,x1、y1为终点坐标*/*/void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1) char dx;/直线x轴差值 char dy;/直线y轴差值 char dx_sym;/x轴增长方向,为-1时减值方向,为1时增值方向 char dy_sym;/y轴增长方向,为-1时减值方向,为1时增值方向 char dx_x2;/dx*2值变量,用于加快运算速度 char dy_x2;/dy*2
16、值变量,用于加快运算速度 char di; /决策变量 if(x0 = x1)/判断是否为垂直线 gui_rline(x0 , y0 , y1);/画垂直线 return; if(y0 = y1)/判断是否为水平线 gui_hline(x0 , x1 , y0);/画水平线 return; dx = x1 - x0;/求取两点之间的差值 dy = y1 - y0; /*判断增长方向,或是否为水平线、垂直线、点*/ if(dx 0)/判断x轴方向 dx_sym = 1; else if(dx 0)/判断y轴方向 dy_sym = 1; else if(dy = dy)/对于dx=dy,使用x轴为
17、基准 di = dy_x2 - dx; while(x0 != x1) lcd_set_dot(x0,y0); x0 +=dx_sym; if(di 0) di += dy_x2;/计算出下一步的决策值 else di += dy_x2 - dx_x2; y0 += dy_sym; lcd_set_dot(x0, y0);/显示最后一点 else /对于dxdy使用y轴为基准 di = dx_x2 - dy; while(y0 != y1) lcd_set_dot(x0, y0); y0 += dy_sym; if(di 50) with = 50; dx = x1-x0; / 求取两点之间的差值 dy = y1-y0; wx = with/2; wy = with-wx-1; /判断增长方向,或是否为水平线、垂直线、点 if(dx0) / 判断x轴方向 dx_sym = 1; / dx0,设置dx_sym=1 else if(dx0) dx_sym = -1; / dx0,设置dx_sym=-1 else /dx=0,画垂直线,或一点 wx = x0-wx; if(wx=wy) break; wx+; return; if(dy0) / 判断y轴方向 dy_sym = 1; / dy0,设置dy_sym=1 else if(dy
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1