当前位置:首页 >> 信息与通信 >>

基于51单片机的lcd12864的画图程序


1、打点部分 /******************************************************** 名称:GUI_Point(打点) 说明:X:横坐标(代表列的位置,0~127) 把数据重新写入 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~31) Write_command(0x36); /***X,Y 坐标互换,即普通的 X,Y 坐标***/ x_Dyte=x/16; x_byte=x&0x0f; y_Dyte=y/32; y_byte=y&0x1f; Write_command(0x80+y_byte); Write_command(0x80+x_Dyte+8*y_Dyte); yte 选定上下屏 Read_data(); GDRAM_hbit=Read_data(); GDRAM_lbit=Read_data(); delay_us(5); if(flag==1) { Write_command(0x80+y_byte); Write_command(0x80+x_Dyte+8*y_Dyte); _Dyte 选定上下屏 delay_us(5); if(x_byte<8) 低8位 { //判断其在高 8 位, 还是在 //设定行地址(y 坐标) //设定列地址(x 坐标),并通过 8*y //读取当前显示高 8 位数据 //读取当前显示低 8 位数据 //计算在 16 个字节中的哪一个 //计算在该字节中的哪一位 //0 为上半屏,1 为下半屏 //计算在 0~31 当中的哪一行 //设定行地址(y 坐标) //设定列地址(x 坐标),并通过 8*y_D //绘图模式命令 //定义为上下两个屏(取值为 0,1), //定义列地址的字节位, 及在字节中的 Y:纵坐标(代表行的位置,0~63) 根据 Datesheet 需先把数据写到 GDRAM,读取当前位置的数据,经过或和移位后再

Write_data(GDRAM_hbit|(0X01<<(7-x_byte))); Write_data(GDRAM_lbit); } else { Write_data(GDRAM_hbit); Write_data(GDRAM_lbit|(0x01<<(15-x_byte))); } } else { Write_data(0x00); Write_data(0x00); } } 2、画线部分 先看程序

//显示 GDRAM 区高 8 位数据

//显示 GDRAM 区低 8 位数据

//清除 GDRAM 区高 8 位数据 //清除 GDRAM 区低 8 位数据

/******************************************************** * 名称: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) s1=1; else s1=-1; dy=y1-y0; if(dy>=0) //判断 Y 的方向是增加还是降到的 //X 的方向是降低的 //X 的方向是增加的 //定义起点到终点的横、纵坐标增加值

s2=1; else s2=-1; Dx=fabs(x1-x0); Dy=fabs(y1-y0); if(Dy>Dx) { us=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); //纵向上没有增量,画一条垂直线 //横向上没有增量,画一条水平线 // //以 45 度角为分界线,靠进 Y 轴是 status=1,靠近 X 轴是 stat //计算横、纵标志增加值的绝对值

/*********Bresenham 算法画任意两点间的直线********/ sub=2*Dy-Dx; for(i=0;i<Dx;i++) { GUI_Point(x0,y0,1); if(sub>=0) { if(status==1) x0+=s1; else y0+=s2; sub-=2*Dx; } if(status==1) y0+=s2; else x0+=s1; sub+=2*Dy; //判断下下个点的位置 //在靠近 X 轴区,y 值加 1 //在靠近 Y 轴区,x 值加 1 //画点 //第 1 次判断下个点的位置

} } 下面是图片:在(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 6 5 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); GUI_Point(x0+b,y0-a,1); GUI_Point(x0-a,y0+b,1); GUI_Point(x0-b,y0-a,1); GUI_Point(x0-a,y0-b,1); GUI_Point(x0+b,y0+a,1); GUI_Point(x0+a,y0-b,1); GUI_Point(x0+a,y0+b,1); 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 为半径画的圆(小问题是当圆大后,会有部分画不出来,有待 完善) //3 //0 //1 //7 //2 //4 //5 //6 //判断下个点位置的标志 3 1 2

(原文件名: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++) { Write_data(*pic); //列位置 //行位置 //256/8=32 byte //列位置每行自动增加 //扩展指令动作 //扩展指令动作 //上半屏显示

pic++; } } for(i=0;i<32;i++) { Write_command(0x80|i); Write_command(0x88); for(j=0;j<16;j++) { Write_data(*pic); pic++; } } Write_command(0x30); } 下面是照片 //列位置 //行位置 //256/8=32 byte //下半屏显示

(原文件名: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; for(j=0;j<16;j++) { Write_command(0x80+Y_byte+j); Write_command(0x80+X_byte+8*Y_Dyte); delay_us(5); Write_data(*pin++); Write_data(*pin++); } } 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);

//0~31 行中哪一行

//计算行地址 //8*Y_Dyte 上下屏标志,确定列地址 //显示高 8 位数据 //显示低 8 位数据

//"同"

//"一 "

//"个"

//"梦"

//"想"

//以显示区域画一个边框

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 点来处理。


相关文章:
基于51单片机的12864液晶画点程序
基于51单片机的12864液晶画点程序_电子/电路_工程科技_专业资料。#include<reg51...(0x34); //开启扩展指令,关闭绘图显示 com(Y); //写入所确定的点的行位...
基于51单片机的12864画图程序
基于51单片机的12864画图程序_信息与通信_工程科技_专业资料。#include <reg52.h> sbit LCD_RS=P1^0; sbit LCD_RW=P1^1; sbit LCD_E=P1^2; sbit PSB ...
基于51单片机的年历程序,12864液晶显示
基于51单片机的年历程序,12864液晶显示_电子/电路_工程科技_专业资料。#include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit LCD_RS=...
12864显示程序,画点程序,51单片机程序,C语言
12864显示程序,画点程序,51单片机程序,C语言_信息与通信_工程科技_专业资料。12864...只要我们能点亮液晶的任意一个像素点, 那么绘图就不是什么难事了。万丈高楼平...
基于51单片机的12864LCD显示驱动
龙源期刊网 http://www.qikan.com.cn 基于 51 单片机的 12864LCD 显示驱动 作者:范宜衡 操瑞杰 来源:《中国机械》2013 年第 18 期 摘要:利用 51 单片机对 ...
基于51单片机12864显示程序
51单片机12864液晶显示 4页 免费 12864画点程序() 3页 免费 12864各种画图程序(带字库... 24页 5财富值如要投诉违规内容,请到百度文库投诉中心;如要提出功能问...
12864各种画图程序(带字库)
12864绘图版(1)(包括打点、... 3页 免费 基于51单片机的lcd12864的... 11...基于st7920的12864各种画图程序基于st7920的12864各种画图程序隐藏>> /***...
基于51单片机的12864万年历
基于51单片机的12864万年历_电子/电路_工程科技_专业资料。基于51单片机额的12864液晶显示的万年历C语言代码 #include <reg51.h> // 该程序具有显示日期、月份、...
基于51单片机控制的液晶显示屏C程序设计
基于51单片机控制的液晶显示屏C程序设计_电子/电路_工程科技_专业资料。龙源期刊...可以由单片机控制显示 8× 4 个 16× 16 点阵汉字。 1.2.2 TG12864 相关...
更多相关标签:
lcd12864 51单片机 | lcd12864与单片机连接 | 单片机lcd12864 | lcd12864画图 | lcd12864怎么画图 | lcd12864 | lcd12864中文资料 | lcd12864引脚图 |