当前位置:文档之家› 12864显示图形

12864显示图形

看到工具箱旁边那个LCD12864很久没用了(当初买回来用的时候只是简单地测试了一下),于是萌生了重新写一次接口程序的想法(而且这次要给它加个图片显示的功能),好,说做就做,就用Atmega16和ICCAVR来做吧,最近这MCU和平台用得比较熟练。

马上从书堆里把当初打印出来的中文datasheet给翻了出来,依葫芦画瓢地写了个初始化程序。

好,OK。

编译通过。

于是又写了一个可以自定义从XY坐标值开始输出显示的函数,再次编译,也通过,OK。

于是呼马上写了四行简单的字符烧到单片机上试了一下,嘿嘿,一次通过。

如下图:后来在进一步测试的时候也出了点小问题。

就是我是使用USBISP烧写器把程序烧写进AVR的(此时实验板由USBISP烧写器供电),想要实现从第一行的第一个字符开始连续显示"0123456789"。

刚烧写完程序后能看到LCD12864上正常显示"0123456789",但是把烧写器从实验板上断开连接,单独用USB给实验板供电的时候,LCD的第一行只是显示"123456789",第一个字符消失了……,左思右想地弄了一个多小时后,终于把问题给解决了,就是把初始化程序的延时适当增加了些,真是奇怪。

刚开始一直想不通为什么在烧写器供电的情况下就正常显示,而换到USB供电后就出了问题。

后来再想想,估计是跟供电有关。

在使用USBISP烧写器供电的时候,LCD的背光灯明显比用USB供电的时候来得亮,而且对比度也高很多,看来是因为换到USB供电后,供电不怎么充足,以至于LCD在上电初始化的时候花上了更多的时间去初始化(因为供电低了,功率小了,跑起来有点力不从心,用的时间就久了嘛……我是觉得可以这样去理解的接下来呢,就到了有点难度的画图了。

当初刚买到12864的时候只是简单测试了字符显示功能,除了因为画图还不需要用到,另外一个原因就是那datasheet上关于画图那部分的内容不怎么看得懂…。

现在重新拿起来看,依然一头雾水……。

马上上网百度了一下“12864 7920 显示图片”,看到了不少的例子程序,可是……就是没看到有关于这部分功能实现的详细思路和讲解……下载下来的那些程序,基本上没注释,不是说晦涩难懂,但是至少看起来一团糟,让人家不想继续看下去……于是还是硬着头皮去啃那datasheet。

上面对于画图这部分的内容是这样讲解的:在仔细研究了上面关于它的 X啊 Y啊那些坐标的定位啊写满了哪些地址会自增啊哪些不会啊什么的,最后感觉脑袋里有了一种朦胧的概念……哟西,反正不会弄坏,就先随便写个程序试试。

于是乎,嘀咕嘀咕……捣鼓捣鼓……反反复复又弄了一个多小时后,终于摸清了它显示的规律……LCD12864实现画图功能的思路:首先,画图指令属于扩充指令集,要使用这些指令必须在12864初始化之后写命令字(0x34????36吧)进入扩充指令集设定状态。

接着要做的事就是指定我们的图片要从哪里写入(即写入的XY坐标,这个是最关键,也是最难理解的部分)。

因为我们这里是显示一整个画面的图片,所以我们就从12864的第一个点开始显示。

那这个点的坐标是怎么定位的呢?我们往这个点写入数据后,要是接着再写数据,那坐标值会怎样变化呢?首先我们要弄清楚12864究竟是怎么把数据写入到GDRAM(绘图显示RAM)中去的。

12864(ST7920驱动芯片)把屏幕分成上下两部分(如上图中把垂直坐标分成了两部分的00~1F)。

当我们把坐标值写给LCD后(怎么写后面会说),ST7920控制芯片对LCD屏幕的控制过程可以用下面的图片来表示:(后来发现下面那幅图片有点问题……它这里在水平坐标上的00到0F,应该理解为是同一面的,也就是在12864上,水平坐标00到0F处于同一面,而不是上下屏的关系,[看00行]其实大家只要看箭头,明白控制芯片是按什么顺序写GDRAM的就可以了^_^)如图片上所标注,在向GDRAM中写入要显示的图片时,我们先指定从X:00、Y:00处(也就是第①处)开始写入数据(如何指定后面会说明),我们先在第①处写图形数据(按照图片所标注,第15位在最左边,第0位在最右边,即在写入的时候LCD会先写高位字节,接着再写低位字节),接着LCD会自动把坐标定位到同一行第②处的开头,此时我们可以接着告诉LCD在这里写入图形数据,依此类推,当我们写满16次后,第00行(包括上半屏和下半屏的)就全写满了。

那么我们接下去写入数据会出现什么情况呢?答案是LCD又自动从第00行的第①处重新开始写了。

这是因为ST7920控制芯片设计出来就这样,在写入的时候它只会在水平方向(X轴上)地址自增,并且在增加到0F地址之后就会变成00地址从头开始写。

从这里我们可以明白,每次写满一行(共16部分)后就必须在程序里人为地把垂直方向(Y轴)的地址加1,不然就会造成只是在同一行重复写入的现象(俺前面试验了好多次都是这个问题)。

如何在写入的时候定位初始XY坐标呢?依据datasheet,进行坐标设定的时候首先设垂直地址,接着设定水平地址,这两个指令是连续写入LCD的(就是进入扩充指令集设定状态后,只需要RS引脚置低电平,RW引脚置低电平,接着连续写入上面两个命令,垂直地址在前,列地址在后就可以了),我们先来看看关于设定GDRAM地址的指令:从上面的表格我们可以看到,垂直(列)地址由AC6~AC0指定,我们是从00列开始,那自然就是AC6~AC0全为0喽(这里有个问题需要注意,因为我们在写图片数据的时候是一个字节一个字节连续写入的,所以指定列地址的时候就必须为8的整数倍,呵呵,每个字节有8位嘛),那最终写给LCD的指令是如何的呢?就是上面表格紫色字体的部分,例如我是从00列开始写,AC6~AC0为全0,那就是1AC6AC5AC4AC3AC2AC1AC0,也就是1000 0000(二进制),即0x80(十六进制)。

写完列地址就开始写水平(行)地址了,行地址由AC3~AC0指定,我们从00行开始,所以就是全0,就是1000AC3AC2AC1AC0,也就是1000 0000,即0x80。

1.初始化LCD(如果之前已经有先进行过初始化,则这一步省略)2.给LCD写指令0x34,进入扩充指令集设定状态3.设定GDRAM的列地址和行地址【垂直和水平地址】4.按正确规律(每写满一行,行地址要用程序手动加1)连续写入图形数据5.给LCD写指令0x36,打开绘图开关(这样做写入的图形才能正常显示)6.给LCD写指令0x30,返回基本指令集设定状态(也就是正常的字体显示状态)我们在用C语言设计画图程序时,可以这样写(大家如果对写屏的过程不了解,可以把通过改一下下面的程序,例如把写下半屏的函数给屏蔽掉,然后烧写到单片机上看实际效果,这样可以帮助你更好理解这个程序):void LCD_DrawPic(uchar flash pic[64][16]) //定义一个函数,用来向整个屏幕画图{ //图片数据为数组形式,格式为64行16列,正好对应12864的屏幕uchar i,j; //图片数据如何生成请看下面LCD_Write(lcdcmd,0x34); //笔者自定义的函数,功能为向LCD写入命令0x34,即进入扩充指令集设定状态for(i=0;i<32;i++) //定义32次循环,先写半屏数据(半屏共32行) {LCD_Write(lcdcmd,0x80|i); //0b1000 0000写列地址,列地址在增加LCD_Write(lcdcmd,0x80); //0b1000 0000写行位置for(j=0;j<16;j++) //每行共有16部分{LCD_Write(lcddata,pic[i][j]);//笔者自定义的函数,功能为向LCD写入数据}}for(i=0;i<32;i++) //再写剩下的半屏数据{LCD_Write(lcdcmd,0x80|i); //0b1000 0000写列位置LCD_Write(lcdcmd,0x88); //0b1000 1000写行位置for(j=0;j<16;j++){LCD_Write(lcddata,pic[i+32][j]);}}LCD_Write(lcdcmd,0x36);//向LCD写入命令0x36,即打开绘图开关,此时显示图形LCD_Write(lcdcmd,0x30);//向LCD写入命令0x30,返回基本指令集设定状态}那用来做图片的数据应该如何准备呢?这时候我们就要用到字模软件了,网上有很多这方面的软件,在这里我们使用晓奇工作室的LCMZIMO这个软件来作说明。

首先选一幅图片,然后用图像编辑软件截取128*64像素大小,然后转换成单色BMP图片。

原始图片调整大小为128*64调整为单色128*64 BMP格式图片接着使用LCM字模软件打开图片,按照图示的顺序依次设定,打开准备好的图片,然后点参数确认,最后点数据保存,则图片被转换为64行16列的数组数据:转换后所得到的数据:///////////////////////////////////////////////////////////////////// ////// Bitmap点阵数据表 //// 图片: C:\..\桌面\tp2.bmp,横向取模左高位,数据排列:从左到右从上到下 //// 图片尺寸: 128 *64 /////////////////////////////////////////////////////////////////////// ////unsigned char code nBitmapDot[] = // 数据表,这里“nBitmapDot[] ”修改为pic1[64][16]即可(pic1名字可自定义){……(图形数据省略)};接下来就是把这个数组和画图函数整合到你的程序里去然后就可以画出精美的图片啦!附:程序效果演示视频:。

相关主题