第三讲 单片机C语言之12864液晶显示

来源:互联网 发布:sabayon linux 中文 编辑:程序博客网 时间:2024/06/05 10:06

上一讲我们探索了12864的文本模式,这一讲我们来看看绘图模式。上一讲中我们给出了绘图模式的点阵图(见下图),是由512组每组16个点构成的点阵。屏幕分为上下两半,其中每一半占256组;上半部分X轴方向(0-7),Y轴方向(0-31);下半部分X轴方向(8-15),Y轴方向(0-31)。如果一个点为高电平,则被点亮。12864只能以组为单位控制,因此我们只要给一个16位的二进制,就可以驱动一组的16个点。下面我们就通过两个实验来演示12864是如何显示一幅图形的。


实验一 点亮点阵的四角的四个组,先上程序。

main.c

#include "reg51.h"#include "12864.h"void main(){LCD_Init();Clean_Draw();Show_Group(0, 0, 0xaaaa);Show_Group(7, 0, 0xaaaa);Show_Group(8, 31, 0xaaaa);Show_Group(15, 31, 0xaaaa);while(1){}}
12864.c

#include "12864.h"#include "stdio.h"sbit LCDRS_CS=P3^5;sbit LCDWR_SID=P3^6;sbit LCDE_CLK=P3^7;/* 数据 0xfa 命令 地址 0xf8*/void delay(u16 x){while(x--);}void LCD_Send8bit(u8 dat) //向LCD发送一个字节{u8 i;for(i=0;i<8;i++){LCDE_CLK=0;LCDWR_SID=dat>>7;LCDE_CLK=1;dat<<=1;}}void LCD_EntryText()  //LCD进入文本模式{LCD_WriteCmd(0x30);}void LCD_EntryDraw(u8 sw) //LCD进入绘图模式{if(sw==0){   LCD_WriteCmd(0x34);}else{   LCD_WriteCmd(0x36);}}void LCD_SetAddText(u8 add)//设置LCD文本模式显示地址{LCD_WriteCmd(0x30);LCDE_CLK=0;LCDRS_CS=1;LCD_Send8bit(0Xf8);LCD_Send8bit(add&0xf0);LCD_Send8bit(add<<4);LCDE_CLK=0;LCDRS_CS=0;}void LCD_SetAddDraw(u8 x, u8 y)//设置LCD绘图模式显示地址{LCD_WriteCmd(y|0x80);LCD_WriteCmd(x|0x80);}void LCD_WriteDat(u8 dat)//向LCD写入显示数据{LCDE_CLK=0;LCDRS_CS=1;LCD_Send8bit(0Xfa);LCD_Send8bit(dat&0xf0);LCD_Send8bit(dat<<4);LCDE_CLK=0;LCDRS_CS=0;}void LCD_WriteCmd(u8 cmd) //向LCD发送一条命令{LCDE_CLK=0;LCDRS_CS=1;LCD_Send8bit(0Xf8);LCD_Send8bit(cmd&0xf0);LCD_Send8bit(cmd<<4);LCDE_CLK=0;LCDRS_CS=0;}void Show_Chinese(u8 add, u8 mh, u8 ml)//在LCD上显示一个中文{LCD_EntryText(); //lcd进入文本模式LCD_SetAddText(add);LCD_WriteDat(mh);LCD_WriteDat(ml);}void Show_String(u8 add, u8 *str)//lcd显示字符串{LCD_SetAddText(add);while(*str){LCD_WriteDat(*str++);}}void Show_Number(u8 add, u16 n)  //lcd显示一个数字{char s[6];sprintf(s,"%05d",n);Show_String(add, s);}void Show_Float(u8 add, float n) //lcd显示一个浮点数{char s[6];sprintf(s,"%03.2f",n);Show_String(add, s);}void LCD_Init(){LCD_EntryText();  //lcd进入文本模式delay(50);LCD_WriteCmd(0x01);//清屏delay(5000);LCD_WriteCmd(0x0c); //开显示delay(50);Clean_Draw();}//-----------------------------------------////-------------------绘图模式--------------////-----------------------------------------//void Show_Group(u8 x, u8 y,u16 dat)  //显示LCD绘图模式的一组点{LCD_EntryDraw(0);//进入绘图模式 关闭LCD_SetAddDraw(x,y);  //LCD_WriteDat(dat>>8); // 不能用等于号,否则改变datLCD_WriteDat(dat); //LCD_EntryDraw(1); //进入绘图模式 打开}void Clean_Draw(){u8 i;u8 j;for(i=0;i<16;i++){for(j=0;j<32;j++){Show_Group(i,j,0);  //调用512次,每次都有关闭打开,会在下个实验改进}}}

12864.h
#include "reg51.h"#include "stdio.h" #define u8 unsigned char #define u16 unsigned int void delay(u16 x); void LCD_EntryText(); void LCD_EntryDraw(u8 sw); void LCD_SetAddText(u8 add); void LCD_SetAddDraw(u8 x, u8 y); void LCD_WriteDat(u8 dat); void LCD_WriteCmd(u8 cmd); void LCD_Send8bit(u8 dat); void Show_Chinese(u8 add, u8 mh, u8 ml); void Show_String(u8 add, u8 *str); void Show_Number(u8 add, u16 n); void Show_Float(u8 add, float n); void LCD_Init(); void Show_Group(u8 x, u8 y,u16 dat);  //显示LCD绘图模式的一组点 void Clean_Draw();  #endif
程序分析:整个程序的目标是要能控制一个组的16个点阵,那么首先我们要进入绘图模式,然后设置显示地址(x,y), 再就是写16位数据。先看进入绘图模式,由12864数据手册知道,绘图模式进入后有绘图显示on与绘图显示off两种操作,这个on打开与off关闭又是怎么操作的?数据手册规定如下。


因此我们首先要关闭绘图显示,也就是写指令LCD_WriteCmd(0x34),我们把这两个关闭与打开指令都放到了LCD_EntryDraw(u8 sw)函数,其中sw为1时打开,为0时关闭。接下来要设置地址,我们新建LCD_SetAddDraw(x,y)函数,分别写入XY地址,注意最高位始终为1(如下图)所以要并上0x80。


接下来便是写入16位数据,分两次,先写高8位,因此先要将数据右移8位,再写低8位,只需整个数据写入即可,因为writedat函数会自动截取低8位。最好再打开绘图显示,完成。整个过程我们放在Show_Group(u8 x, u8 y,u16 dat) 函数。

void Show_Group(u8 x, u8 y,u16 dat)  //显示LCD绘图模式的一组点{LCD_EntryDraw(0);//进入绘图模式 关闭LCD_SetAddDraw(x,y);  //LCD_WriteDat(dat>>8); // 不能用等于号,否则改变datLCD_WriteDat(dat); //LCD_EntryDraw(1); //进入绘图模式 打开}
最后还要注意新建一个清屏函数Clean_Draw(),在每次显示之前清屏,其实就是令所有点为0,这样可以保持整个屏幕不出现乱码。


实验二 显示一幅图片

前面我们分析了LCD的点阵分布,分上下两块,而每一块正好有128X32个点,对应一幅128X32的像素图。因此如果我们有一幅128X64个像素点图,那么完全可以用12864来表达。因此首先要将这样一幅图导入到画图软件,生成后缀名为.bmp的128X64黑白、单色文件,再用PCtoLCD2002软件生成一个二进制文件,再将二进制数值复制到工程文件picture.c中,并做成一个数组保存到ROM中。如下:

#include "picture.h"code unsigned char pic1[]={0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x01,0xFC,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x07,0xFE,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x3F,0x87,0x80,0x00,0x00,0x00,0x00,0x1E,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x7E,0x03,0xC0,0x00,0x00,0x00,0x00,0x0F,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x01,0xC0,0x00,0x00,0x00,0x00,0x07,0xC0,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0xC0,0x00,0x00,0x00,0x00,0x03,0xE0,0xF8,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x01,0xE0,0x00,0x00,0x00,0x00,0x01,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xF8,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0x00,0x3F,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x0F,0xF0,0x01,0xC0,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFC,0x00,0x3F,0x80,0x01,0xC0,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF8,0x00,0x7E,0x0F,0xFF,0xFC,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x78,0x1F,0xFF,0xFE,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x00,0xF0,0x1F,0xFF,0xFF,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0xE0,0x1F,0x87,0x8F,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0xE0,0x1F,0xC7,0x3F,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0xE0,0x0F,0xC7,0xFF,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0xFF,0xFF,0xFF,0xFC,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x7F,0xFF,0xFF,0xE0,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x3F,0xFF,0xFF,0x80,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0x00,0x00,0x00,0x38,0x00,0x01,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x78,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFC,0x00,0x78,0x03,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x1F,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x0F,0x80,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x07,0xC0,0x00,0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x01,0xF0,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x7C,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x3E,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF0,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00};

接下来我们要将数组中的每两个数据(也就是16位)去驱动一个组,这样数组的1024个数据便可覆盖LCD的512组。新建一个图片显示函数到12864.c中,另外我们修改Show_Group函数成Show_GroupX函数,这样做的好处不用频繁地进行关闭和打开绘图显示。另外一个要注意的地方是Show-Picture函数中指针的使用。如何将数组中相邻的两个数据组合成一个16位数据呢?我们可以使用中间变量t,t=*p++; t<<=8;t|=*p++;,这样完全行得通。但是使用指针的话,则避免了重复性的操作,减轻了系统负担。

void Show_GroupX(u8 x, u8 y,u16 dat)  //显示LCD绘图模式的一组点{LCD_SetAddDraw(x,y);  //LCD_WriteDat(dat>>8); // 不能用等于号,否则改变datLCD_WriteDat(dat); //}void Show_Picture(u8 *p)//显示一幅128*64的图片{u16 *u;u8 x,y;u=(u16*) p;LCD_EntryDraw(0);for(y=0;y<32;y++){for(x=0;x<8;x++){Show_GroupX(x,y,*u++); }}for(y=0;y<32;y++){for(x=8;x<16;x++){Show_GroupX(x,y,*u++); }}LCD_EntryDraw(1);}
最后我们只需要在main函数中显示图片即可。

#include "12864.h"#include "picture.h"void main(){LCD_Init();Clean_Draw();Show_Picture((u8*)pic1);while(1){}}

picture.h

#ifndef _picture_#define _picture_code unsigned char pic1[];#endif




原创粉丝点击