基于51单片机的lcd12864的画图程序.docx
- 文档编号:10543556
- 上传时间:2023-05-26
- 格式:DOCX
- 页数:12
- 大小:336.54KB
基于51单片机的lcd12864的画图程序.docx
《基于51单片机的lcd12864的画图程序.docx》由会员分享,可在线阅读,更多相关《基于51单片机的lcd12864的画图程序.docx(12页珍藏版)》请在冰点文库上搜索。
基于51单片机的lcd12864的画图程序
1、打点部分
/********************************************************
名称:
GUI_Point(打点)
说明:
X:
横坐标(代表列的位置,0~127) Y:
纵坐标(代表行的位置,0~63)
根据Datesheet需先把数据写到GDRAM,读取当前位置的数据,经过或和移位后再把数据重新写入
GDRAM每行有16个位元,共64行,每个位元有两个8位(高低8位)
计算出在那个位元,在该位元的哪一位
易出现的问题:
1、打点位置的定位
2、读取当前显示的数据
3、或和移位,即重新写人的新数据
********************************************************/
void GUI_Point(uchar x,uchar y,uchar flag)
{
uchar x_Dyte,x_byte; //定义列地址的字节位,及在字节中的哪1位
uchar y_Dyte,y_byte; //定义为上下两个屏(取值为0,1),行地址(取值为0~31)
Write_command(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_command(0x80+y_byte); //设定行地址(y坐标)
Write_command(0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
Read_data();
GDRAM_hbit=Read_data(); //读取当前显示高8位数据
GDRAM_lbit=Read_data(); //读取当前显示低8位数据
delay_us(5);
if(flag==1)
{
Write_command(0x80+y_byte); //设定行地址(y坐标)
Write_command(0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
delay_us(5);
if(x_byte<8) //判断其在高8位,还是在低8位
{
Write_data(GDRAM_hbit|(0X01<<(7-x_byte))); //显示GDRAM区高8位数据
Write_data(GDRAM_lbit); //显示GDRAM区低8位数据
}
else
{
Write_data(GDRAM_hbit);
Write_data(GDRAM_lbit|(0x01<<(15-x_byte)));
}
}
else
{
Write_data(0x00); //清除GDRAM区高8位数据
Write_data(0x00); //清除GDRAM区低8位数据
}
}
2、画线部分
先看程序
/********************************************************
* 名称:
GUI_Line()
采用布兰森汉姆(Bresenham)算法画线
* 功能:
任意两点间的直线。
根据硬件特点,实现加速。
* 入口参数:
x0 直线起点所在行的位置
* y0 直线起点所在列的位置
* x1 直线终点所在行的位置
‘ y1 直线终点所在列的位置
* 出口参数:
无
* 说明:
操作失败原因是指定地址超出缓冲区范围。
*********************************************************/
void GUI_Line8(uchar x0,uchar y0,uchar x1,uchar y1)
{
int temp;
int dx,dy; //定义起点到终点的横、纵坐标增加值
int s1,s2,status,i;
int Dx,Dy,sub;
dx=x1-x0;
if(dx>=0) //X的方向是增加的
s1=1;
else //X的方向是降低的
s1=-1;
dy=y1-y0; //判断Y的方向是增加还是降到的
if(dy>=0)
s2=1;
else
s2=-1;
Dx=fabs(x1-x0); //计算横、纵标志增加值的绝对值
Dy=fabs(y1-y0);
if(Dy>Dx) //
{ //以45度角为分界线,靠进Y轴是status=1,靠近X轴是status=0
temp=Dx;
Dx=Dy;
Dy=temp;
status=1;
}
else
status=0;
/********判断垂直线和水平线********/
if(dx==0) //横向上没有增量,画一条水平线
GUI_XLine(x0,y0,y1,1);
if(dy==0) //纵向上没有增量,画一条垂直线
GUI_YLine(x0,y0,x1,1);
/*********Bresenham算法画任意两点间的直线********/
sub=2*Dy-Dx; //第1次判断下个点的位置
for(i=0;i { GUI_Point(x0,y0,1); //画点 if(sub>=0) { if(status==1) //在靠近Y轴区,x值加1 x0+=s1; else //在靠近X轴区,y值加1 y0+=s2; sub-=2*Dx; //判断下下个点的位置 } if(status==1) y0+=s2; else x0+=s1; sub+=2*Dy; } } 下面是图片: 在(0,0)到(127,32)之间画线 在(0,0)到(63,63)之间画线 大家可以看到,直线越长其线性越差,主要是算法的问题 (原文件名: IMG_1765.JPG) 3、画圆部分 主要思路是用Bresenham算法先画1/8个圆,在利用对称行画出其余的部分 程序如下: /***************************************** 名称: Draw_circle (在任意位置画圆) 说明: 使用Bresenham法画1/8个圆,在用对称性画出其他的7/8个圆 按下图把圆分为8份 0 7 1 6 2 5 3 4 *****************************************/ void Draw_circle(uchar x0,uchar y0,uchar r) { int a,b; int di; a=0; b=r; di=3-2*r; //判断下个点位置的标志 while(a<=b) { GUI_Point(x0-b,y0-a,1); //3 GUI_Point(x0+b,y0-a,1); //0 GUI_Point(x0-a,y0+b,1); //1 GUI_Point(x0-b,y0-a,1); //7 GUI_Point(x0-a,y0-b,1); //2 GUI_Point(x0+b,y0+a,1); //4 GUI_Point(x0+a,y0-b,1); //5 GUI_Point(x0+a,y0+b,1); //6 GUI_Point(x0-b,y0+a,1); a++; /***使用Bresenham算法画圆**/ if(di<0) di +=4*a+6; else { di +=10+4*(a-b); b--; } GUI_Point(x0+a,y0+b,1); } } 这是在以(63,32)为圆心,32为半径画的圆(小问题是当圆大后,会有部分画不出来,有待完善) (原文件名: IMG_1768.JPG) 4、整屏画图部分 这个比较简单,就直接上程序了 void LCD_fulldisplay_picture_2(const uchar *pic) //全屏显示图片方法2 { unsigned int x=0; unsigned char i,j; Write_command(0x34); //扩展指令动作 Write_command(0x36); //扩展指令动作 for(i=0;i<32;i++) //上半屏显示 { Write_command(0x80|i); //列位置 Write_command(0x80); //行位置 for(j=0;j<16;j++) //256/8=32 byte { //列位置每行自动增加 Write_data(*pic); pic++; } } for(i=0;i<32;i++) //下半屏显示 { Write_command(0x80|i); //列位置 Write_command(0x88); //行位置 for(j=0;j<16;j++) //256/8=32 byte { Write_data(*pic); pic++; } } Write_command(0x30); } 下面是照片 (原文件名: IMG_1769.JPG) 5、图片和文字在一起显示 我用的是带字库的,所以显示汉字较简单,即先作图,之后关闭绘图模式,打开普通模式就可以显示汉字了,先上个图片 (原文件名: IMG_1777.JPG) (原文件名: IMG_1776.JPG) 大家有可以已经看出来,同样的图,怎么一幅在“同”字那有边框,另为一幅没有呢? 这个也是我的问题,因为“同一个梦想”是我用点阵的方式扫进去的,而另外的字是用带字库的写进去的,我也搞不懂,还想请大家帮忙呀。 下面是程序 /*************************************************** 名称: LCD_display_zizao (以点阵方式写入汉字或字符) 输入: x(0~127),y(0~63) (输入显示数据的位置) 说明: (此显示位置的确定方法类似打点的程序) ***************************************************/ void LCD_display_zizao(uchar x,uchar y,const uchar *pin) { uchar i,j; uchar X_byte=x/16; //计算在列的那个位元上(一行共16个位元) uchar Y_Dyte=y/31; //上下屏标志位 uchar Y_byte=y&0x1f; //0~31行中哪一行 for(j=0;j<16;j++) { Write_command(0x80+Y_byte+j); //计算行地址 Write_command(0x80+X_byte+8*Y_Dyte); //8*Y_Dyte上下屏标志,确定列地址 delay_us(5); Write_data(*pin++); //显示高8位数据 Write_data(*pin++); //显示低8位数据 } } const uchar hanzi_0[]={ //"同" 0x00,0x04,0x7F,0xFE,0x40,0x04,0x40,0x24, 0x5F,0xF4,0x40,0x04,0x40,0x24,0x4F,0xF4, 0x48,0x24,0x48,0x24,0x48,0x24,0x48,0x24, 0x4F,0xE4,0x48,0x24,0x40,0x14,0x40,0x08}; const uchar hanzi_1[]={ //"一 " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x04,0xFF,0xFE, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; const uchar hanzi_2[]={ //"个" 0x01,0x00,0x01,0x00,0x02,0x80,0x04,0x40, 0x08,0x20,0x11,0x10,0x21,0x0E,0xC1,0x04, 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00}; const uchar hanzi_3[]={ //"梦" 0x08,0x20,0x08,0x24,0xFF,0xFE,0x08,0x20, 0x1C,0x70,0x2A,0xAE,0x49,0x24,0x8C,0x20, 0x07,0xF8,0x0C,0x10,0x14,0x20,0x22,0x40, 0x01,0x80,0x01,0x00,0x0E,0x00,0x70,0x00}; const uchar hanzi_4[]={ //"想" 0x10,0x08,0x11,0xFC,0x11,0x08,0xFF,0x08, 0x11,0xF8,0x31,0x08,0x39,0xF8,0x55,0x08, 0x91,0x08,0x11,0xF8,0x00,0x00,0x12,0x00, 0x51,0x84,0x50,0x92,0x90,0x12,0x0F,0xF0}; /****奥运五环图案****/ void Olympic_rings(void) { draw_rectangular(0,0,127,63); //以显示区域画一个边框 Draw_circle(37,10,10); Draw_circle(64,10,10); Draw_circle(91,10,10); Draw_circle(50,20,10); Draw_circle(78,20,10); LCD_display_zizao(0,32,hanzi_0); //同 LCD_display_zizao(16,32,hanzi_1); //一 LCD_display_zizao(32,32,hanzi_2); //个 LCD_display_zizao(48,32,hanzi_3); //梦 LCD_display_zizao(64,32,hanzi_4); //想 Write_command(0x30); //关闭绘图模式 LCD_Display_Mixed(3,3,"同一个世界 "); //普通模式下输入汉字 } 就为大家讲这么多吧,希望我的东西对大家有用,如果有更优的源码可以交流交流,随便帮我解决那个“同”的问题,哦,对了,用点阵扫进去的位置好像也不怎么对,也请大家给看看啊,按一行128点,一列64点来处理。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 51 单片机 lcd12864 画图 程序