/*******************************************************************************************************/ //:本程序为12864(st7920)驱动程序,仅仅实现了最简单的显示功能 /*******************************************************************************************************/ #include<reg52.h> #include<intrins.h> //内含-NOP-函数 #include<stdlib.h> //内含rand()函数 #define uchar unsigned char #define uint unsigned int //**********宏定义所需指令 #define BASIC_SET 0x30 #define EXTEND_SET 0x34 #define DRAW_ON 0x36 #define DRAW_OFF 0x34 //*************port定义 sbit LCD_RS = P3^5; sbit LCD_RW = P3^6; sbit LCD_EN = P3^4; sbit wela = P2^6; sbit dula = P2^7; //************变量定义 //****************短延时 void delay(uint k) { uint i;uchar j;for(i = 0; i < k ;i ++)for(j = 0; j < 10 ;j ++); } //***********12864写指令函数 void write_com(uchar cmd) { LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;P0 = cmd;delay(5);LCD_EN = 1;delay(5);LCD_EN = 0; } //********12864写数据函数 void write_dat(uchar dat) { LCD_RS = 1; LCD_RW = 0;LCD_EN = 0;P0 = dat;delay(5);LCD_EN = 1;delay(5);LCD_EN = 0; } //****************从LCD中读数据 uchar read_dat(void) { uchar temp;P0 = 0XFF; //释放数据线LCD_RS = 1; //数据LCD_RW = 1; //读模式LCD_EN = 1; //为高电平进行读数据或指令delay(1);temp = P0;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; //第四行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(Alphabet[i]!='\0'){ write_dat(Alphabet[i]); //写入须要显示字符的显示码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坐标{ write_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,unsigned char color) { unsigned char x_Dyte,x_byte; //定义列地址的字节位,及在字节中的哪1位 unsigned char y_Dyte,y_byte; //定义为上下两个屏(取值为0。1),行地址(取值为0~31)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_byte=y&0x1f; //计算在0~31其中的哪一行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*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏delay(1);if(x_byte<8) //推断其在高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(GDRAM_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;//定义两个暂时变量。用于存放读出来的数据write_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_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);//原低位数据送回}else{ write_dat(tmph);//原高位数据送回write_dat(tmpl | (0x01 << (15 - x_bit)));}write_com(DRAW_ON); //打开画图显示write_com(BASIC_SET);//回到基本指令集 } //************画水平线函数**********************************// //x0、x1为起始点和终点的水平坐标。y为垂直坐标***************// //**********************************************************// void gui_hline(uchar x0, uchar x1, uchar y) { uchar bak;//用于对两个数互换的中间变量,使x1为大值if(x0 > 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;}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值变量,用于加快运算速度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)dx_sym = -1;else{ gui_rline(x0 , y0 , y1);return;}}if(dy > 0)//推断y轴方向dy_sym = 1;else{ if(dy < 0)dy_sym = -1;else{ gui_hline(x0 , x1 , y0);return;}}/*将dx、dy取绝对值***********/dx = dx_sym * dx;dy = dy_sym * dy;/****计算2倍的dx、dy值*******/dx_x2 = dx * 1;//我改为了一倍,这样才跟真实的两点相应dy_x2 = dy * 1;/***使用bresenham法进行画直线***/if(dx >= dy)//对于dx>=dy,使用x轴为基准{ 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 //对于dx<dy使用y轴为基准{ di = dx_x2 - dy;while(y0 != y1){ lcd_set_dot(x0, y0);y0 += dy_sym;if(di < 0)di += dx_x2;else{ di += dx_x2 - dy_x2;x0 += dx_sym;}}lcd_set_dot(x0, y0);//显示最后一点} } //***************************************************************************// //*******************画指定宽度的随意两点之间的直线**************************// //參数说明:x0、y0为起始点坐标。x1、y1为终点坐标,with为线宽*****************// //***************************************************************************// void gui_linewith(uchar x0 , uchar y0 , uchar x1 , uchar y1 , uchar with) { 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值变量。用于加快运算速度char di; // 决策变量char wx, wy; // 线宽变量char 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);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, x1, y1);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);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); } 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);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);} } //***********画矩形函数*************************************// //x0、y0为矩形左上角坐标值。x1、y1为矩形右下角坐标值********// //**********************************************************// void gui_rectangle(uchar x0 , uchar y0 , uchar x1 , uchar y1) { gui_hline(x0 , x1 , y0); gui_rline(x0 , y0 , y1); gui_rline(x1 , y0 , y1); gui_hline(x0 , x1 , y1); } //****************画填充矩形函数****************************// //x0、y0为矩形左上角坐标值。x1、y1为矩形右下角坐标值********// //**********************************************************// /*void gui_rectangle_fill(uchar x0 , uchar y0 , uchar x1 , uchar y1) { uchar i;//转换数据的中间变量,使x1、y1大 if(x0 > x1) { i = x0; x0 = x1; x1 = i; } if(y0 > y1) { i = y0; y0 = y1; y1 = i; } //***推断是否是直线***/ /* if(y0 == y1)//画水平线 { gui_hline(x0 , x1 , y0); return; } if(x0 == x1)//画竖直线 { gui_rline(x0 , y0 , y1); return; } while(y0 <= y1)//画填充矩形 { gui_hline(x0 , x1 , y0); y0 ++; } } */ //*******************画正方形函数*************************// //x0、y0为正方形左上角坐标,with正方形边长****************// //********************************************************// /*void gui_square(uchar x0 , uchar y0 , uchar with) { if(with == 0) return; if((x0 + with) > 127)//横轴超出液晶边界 return; if((y0 + with) > 63) return; gui_rectangle(x0 , y0 , x0 + with , y0 + with); } */ //****************画填充正方形函数*************************// //x0、y0为正方形左上角坐标,with正方形边长*****************// //*********************************************************// /*void gui_square_fill(uchar x0 , uchar y0 , uchar with) { if(with == 0) return; if((x0 + with) > 127)//横轴超出液晶边界 return; if((y0 + with) > 63) return; gui_rectangle_fill(x0 , y0 , x0 + with , y0 + with); } */ //****************画圆函数*********************************// //x0、y0为圆心坐标,r为圆的半径****************************// //*********************************************************// void gui_circle(uchar x0 , uchar y0 , uchar r) { char a , b; char di; if(r > 31 || r == 0)//圆大于液晶屏或者没半径则返回 return; a = 0; b = r; di = 3 - 2 * r;//推断下个点位置的标志 while(a <= b) { lcd_set_dot( x0 - b , y0 - a);//3lcd_set_dot( x0 + b , y0 - a); //0lcd_set_dot( x0 - a , y0 + b); //1lcd_set_dot( x0 - b , y0 - a); //7lcd_set_dot( x0 - a , y0 - b); //2lcd_set_dot( x0 + b , y0 + a); //4lcd_set_dot( x0 + a , y0 - b); //5lcd_set_dot( x0 + a , y0 + b); //6lcd_set_dot( x0 - b , y0 + a);a ++;//***使用bresenham算法画圆********/if(di < 0)di += 4 * a + 6;else{ di += 10 + 4 * (a - b);b --;}lcd_set_dot( x0 + a , y0 + b);} } //***************************************************************************// //***************************画正椭圆函数************************************// //说明:给定椭圆的四个点的參数,最左、最右点的x轴坐标值为x0、x1,最上、最下点 // 的y轴坐标为y0、y1. //说明:----------------------------显示效果不好 //***************************************************************************// void gui_ellipse(char x0, char x1, char y0, char y1) { char draw_x0, draw_y0; // 刽图点坐标变量char draw_x1, draw_y1;char draw_x2, draw_y2;char draw_x3, draw_y3;char xx, yy; // 绘图控制变量 char center_x, center_y; // 椭圆中心点坐标变量char radius_x, radius_y; // 椭圆的半径。x轴半径和y轴半径int radius_xx, radius_yy; // 半径乘平方值int radius_xx2, radius_yy2; // 半径乘平方值的两倍char di; // 定义决策变量 /* 參数过滤 */ if( (x0==x1) || (y0==y1) ) return; /* 计算出椭圆中心点坐标 */ center_x = (x0 + x1) >> 1; center_y = (y0 + y1) >> 1; /*计算出椭圆的半径。x轴半径和y轴半径 */if(x0 > x1) { radius_x = (x0 - x1) >> 1; } else { radius_x = (x1 - x0) >> 1; } if(y0 > y1) { radius_y = (y0 - y1) >> 1; } else { radius_y = (y1 - y0) >> 1; } /* 计算半径平方值 */ radius_xx = radius_x * radius_x; radius_yy = radius_y * radius_y; /* 计算半径平方值乘2值 */ radius_xx2 = radius_xx<<1; radius_yy2 = radius_yy<<1; /* 初始化绘图变量 */ xx = 0; yy = radius_y; di = radius_yy2 + radius_xx - radius_xx2*radius_y ; // 初始化决策变量 /* 计算出椭圆y轴上的两个端点坐标,作为作图起点 */ draw_x0 = draw_x1 = draw_x2 = draw_x3 = center_x; draw_y0 = draw_y1 = center_y + radius_y; draw_y2 = draw_y3 = center_y - radius_y; lcd_set_dot(draw_x0, draw_y0); // 画y轴上的两个端点 lcd_set_dot(draw_x2, draw_y2); while( (radius_yy*xx) < (radius_xx*yy)) { if(di<0){ di+= radius_yy2*(2*xx+3);}else{ di += radius_yy2*(2*xx+3) + 4*radius_xx - 4*radius_xx*yy;yy--;draw_y0--;draw_y1--;draw_y2++;draw_y3++; }xx ++; // x轴加1draw_x0++;draw_x1--;draw_x2++;draw_x3--;lcd_set_dot(draw_x0, draw_y0);lcd_set_dot(draw_x1, draw_y1);lcd_set_dot(draw_x2, draw_y2);lcd_set_dot(draw_x3, draw_y3); } di = radius_xx2*(yy-1)*(yy-1) + radius_yy2*xx*xx + radius_yy + radius_yy2*xx - radius_xx2*radius_yy; while(yy>=0) { if(di<0){ di+= radius_xx2*3 + 4*radius_yy*xx + 4*radius_yy - 2*radius_xx2*yy;xx ++; // x轴加1 draw_x0++;draw_x1--;draw_x2++;draw_x3--; }else{ di += radius_xx2*3 - 2*radius_xx2*yy; }yy--;draw_y0--;draw_y1--;draw_y2++;draw_y3++;lcd_set_dot(draw_x0, draw_y0);lcd_set_dot(draw_x1, draw_y1);lcd_set_dot(draw_x2, draw_y2);lcd_set_dot(draw_x3, draw_y3);} } //******************************************************************* //*******画满屏图片-----本程序为逐行写,因此图片数据也应该是逐行取的 //參数:dat为填充的数据------用本程序时须要满屏图的数组 //******************************************************************* void gui_draw_full_picture (unsigned char *dat) { unsigned char i; unsigned char j; unsigned char k; unsigned char bGDRAMAddrX = 0x80; //GDRAM水平地址 unsigned char bGDRAMAddrY = 0x80; //GDRAM垂直地址 for(i = 0; i < 2; i++) { for(j = 0; j < 32; j++) { for(k = 0; k < 8; k++) { write_com(0x34); //设置为8位MPU接口,扩充指令集,关闭画图显示write_com(bGDRAMAddrY+j); //垂直地址Y write_com(bGDRAMAddrX+k); //水平地址X write_dat(*dat++); //写数据高字节write_dat(*dat++); //写数据低字节} } bGDRAMAddrX = 0x88; //写下半屏幕} write_com(0x36); //打开画图模式write_com(0x30); //恢复基本指令集。关闭画图模式 } unsigned char code DCB2HEX_TAB[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; //****************************输出一行数据函数。此行可随意长,不必非得是8的倍数**和下个函数合用画随意大小(矩形)的图形或汉字 //參数:flag反显标志,1为反显 ,x、y为指定显示位置的起始点。*dat要输出的点阵数组,no显示此行所需的点个数,即图形一行的点数 void gui_loadline(unsigned char x,unsigned char y,unsigned char *dat,unsigned char no,unsigned char flag) { unsigned char bit_dat; unsigned char i; /* 參数过滤,若指定显示位置超出液晶屏则返回 */ if(x>127) return; if(y>63) return; for(i=0; i<no; i++)//超出本行所规定的点数则本行显示完毕 { /* 推断是否要读取点阵数据,每字节的開始读取一次点阵数组即i为8的倍数时 */ if( (i%8)==0 ) bit_dat = *dat++; /* 对对应的点打1或打0。 i&0x07意思是对8求余*/ if( (bit_dat&DCB2HEX_TAB[i&0x07])==0 )//取出i相应的位,并推断是否为0 { if(flag==0) //推断是否反显,该位取出的数据为0,反显要打为1,flag==0代表不反显 GUI_Point(x,y,0); //正常显示0,GUI_Point(x,y,0)代表在x、y处打0 else GUI_Point(x,y,1); //将0反显 } else { if(flag==0) GUI_Point(x,y,1); else GUI_Point(x,y,0); } if( (++x)>127) return;//若显示超出了液晶屏则返回 } } //*************************************************************************** //*****************在自己定义大小的区域内绘图或画字函数**************************** //參数说明: x、y指定显示区域的起始点坐标 // dat 要输出显示的图形或汉字点阵数组。 // hno 要显示区域的长度 // lno 要显示区域的高度 // flag反显标志,1为反显 //**************************************************************************** void GUI_Put_Area(unsigned char x,unsigned char y,unsigned char *dat,unsigned char hno,unsigned char lno,unsigned char flag) { unsigned char i;for(i=0;i<lno;i++)//逐行打点,打点行数要小于区域高度{ gui_loadline(x,y,dat,hno,flag); // 打一行数据y++; //使指针指向下一行dat += (hno>>3); //比方说上一行打了2字节,此处的意思是使数据向后推进2字节,(hno>>3)意思是算出上一行有几个字节数据if((hno&0x07)!=0) //hno&0x07意思是对8求余,因一行不满整字节时,上一句的意思就是算出上一行的整字节数,但实际上在取模时不满一个dat++; //字节也按一个字节取,所以上一句少计算了一个字节。这里加上} } //*********************************************************************************以上为GDRAM画图部分************************************************************************// //**********************************************************************************下面为CGRAM自己定义字库部分******************************************************************// //******************************************************** //设置CGRAM字库 //ST7920 CGRAM(用户自己定义图标)空间分布 //空间1地址:40H~4FH共16个地址,一个地址相应两个字节数据;相应调用码:0000H //空间2地址:50H~5FH共16个地址,一个地址相应两个字节数据;相应调用码:0002H //空间3地址:60H~6FH共16个地址,一个地址相应两个字节数据;相应调用码:0004H //空间4地址:70H~7FH共16个地址,一个地址相应两个字节数据;相应调用码:0006H //參数说明:num为空间编号。取1、2、3、4,CGRAM_ZIKU为地址指针 void SET_CGRAM(unsigned char num,unsigned char *CGRAM_ZIKU) { unsigned char i,add;write_com(0x34); //再次设置为8位并行口。扩展指令集write_com(0x02); //SR=0,同意设置CGRAM地址write_com(0x30); //恢复设置为8位并行口,基本指令集add=(num<<4)|0x40; //计算CGRAM的首地址for(i=0;i<16;i++){ write_com(add+i); //设置CGRAM的首地址write_dat(CGRAM_ZIKU[i*2]); //写入高8位数据write_dat(CGRAM_ZIKU[i*2+1]);//写入低8位数据} } //******************************************************** //指定位置显示CGRAM自造字函数 //參数说明:x为行号,y为列号。num为编号 //******************************************************** void display_CGRAM(unsigned char x,unsigned char y,unsigned char num) { set_cursor(x,y); //设置显示的起始地址write_dat(0x00); //写入须要显示汉字的高八位数据write_dat(num*2); //写入须要显示字符的低八位数据 } uchar code CGRAM_ZIKU[] = {0X03,0X80,0X00,0X80,0XF8,0X8E,0X23,0X91,0X22,0X21,0X22,0X20,0X23,0XA0,0X20,0X20, 0X20,0X20,0X20,0X20,0X20,0X20,0X20,0X21,0X20,0X11,0XF8,0X0E,0X00,0X00,0X00,0X00};//I2C //**************设置CGRAM字库并显示函数 void set_and_display() { SET_CGRAM( 1,CGRAM_ZIKU);//把自己定义字库写入CGRAM,且写入空间地址1display_CGRAM(0 , 1 , 1);//在指定的位置显示空间地址1中自己定义的字符 } //***************************************************************************以上为自己定义字库部分**************************************************************// //****************12864初始化函数 void lcd_init() { write_com(0x30);//基本指令操作,8位并口 delay(1); write_com(0x06);//设置为游标右移,DDRAM地址加一。画面不动 delay(1); write_com(0x0c);//显示开,关光标 delay(1); write_com(0x01);//清除lcd显示内容 delay(1); } //*****************************主函数 void main() { wela=0;dula=0;delay(1);lcd_init();//12864初始化函数gui_clear();//绘图时清屏函数delay(10);set_and_display();//显示自己定义字库 gui_circle( 86 , 32 , 30); //画圆gui_linewith( 5 , 5 , 120 , 60 , 3);//画指定线宽直线 gui_ellipse(10 , 120 , 5 , 60);//画正椭圆while(1); }版权声明:本文博客原创文章。博客,未经同意,不得转载。