12864LCD液晶显示原理及使用方法Word格式.docx
《12864LCD液晶显示原理及使用方法Word格式.docx》由会员分享,可在线阅读,更多相关《12864LCD液晶显示原理及使用方法Word格式.docx(12页珍藏版)》请在冰豆网上搜索。
6ENH/LR/W=“L”,E信号下降沿锁存DB7∽DB0
R/W=“H”,E=“H”DDRAM数据读到DB7∽DB0
7DB0H/L数据线
8DB1H/L数据线
9DB2H/L数据线
10DB3H/L数据线
11DB4H/L数据线
12DB5H/L数据线
13DB6H/L数据线
14DB7H/L数据线
15CS1H/LH:
选择芯片(右半屏)信号
16CS2H/LH:
选择芯片(左半屏)信号
17RETH/L复位信号,低电平复位
18VEE-10VLCD驱动负电压
19LED+-LED背光板电源
20LED--LED背光板电源
12864LCD点阵图形液晶模块应用连接电路
液晶驱动设置
在理解12864LCD硬件原理和管脚功能之后,可以针对LCD进行驱动的编写,分两种情况:
仿真环境下和实物开发板编程。
仿真驱动定义如下:
#defineuint8unsignedchar
#defineuint32unsignedint
#defineLCD_databusP0//LCD8位数据口
sbitDI=P2^2;
//DI为0写指令或读状态;
1数据
sbitRW=P2^1;
//RW为1写;
0读
sbitEN=P2^0;
//使能端
sbitCS1=P2^4;
//片选1低电平有效,控制左半屏
sbitCS2=P2^3;
//片选1低电平有效,控制右半屏
实物开发板驱动接线和定义如下
#defineLCD_PORT_NUM0//LCD端口P0
#defineDATA_PORT_NUM1//数据端口P1
#defineCS1_PIN23//片选1低电平有效,控制左半屏
#defineCS2_PIN24//片选1低电平有效,控制右半屏
#defineRST_PIN21//复位信号低电平有效
#defineRW_PIN20//RW为1写;
#defineDI_PIN19//DI为0写指令或读状态;
#defineEN_PIN22//使能端
ucharDIN[8]={24,23,20,21,28,29,19,22};
//8位数据线的接线方式P2.24,P2.23,…P2.22对于D0,D1,…D7,低位到高位
涉及到的一些控制指令:
0x3E关显示,0x3F开显示;
总共有八页,一页占八行点阵点,页的首地址为0xB8;
行的起始地址为0xC0,有规律的改变起始行号可以实现滚屏的效果;
列的起始地址为0x40一直到0x7F共64列;
读状态指令时,数据位最高位D7为1内部忙,为0空闲;
对应接线为P2.22;
通过GPIO_ReadValue获取P2端口的32位数据P2.0到P2.31,然后进行相应的与或操作进行判断。
仿真环境下的驱动程序编写:
voiddelay(uint8i)//延时函数
{
while(--i);
}
voidRead_busy()//读忙函数——数据位的最高位D7为1则忙
P0=0X00;
DI=0;
RW=1;
EN=1
while(P0&
0x80)
;
EN=0;
voidwrite_LCD_command(uint8value)//写命令函数
Read_busy();
//每次读写都要忙判断
//选择命令
RW=0;
//读操作
LCD_databus=value;
EN=1;
//EN由1—0锁存有效数据
_nop_();
voidwrite_LCD_data(uint8value)//写数据函数
DI=1;
//选择数据
voidSet_page(uint8page)//设置显示起始页
page=0xB8|page;
//页的首地址为0xB8
wite_LCD_command(page);
voidSet_line(uint8startline)//设置显示的起始行
startline=0xC0|startline;
write_LCD_command(startline);
voidSet_column(uint8column)//设置显示的列
column=column&
0x3F;
//列的最大值为64
column=column|0x40;
//列的首地址为0x40
write_LCD_command(column);
voidSetOnOff(uint8onoff)//显示开关函数;
0x3E是关显示,0x3F是开显示
onoff=0x3E|onoff;
write_LCD_command(onoff);
voidSelectScreen(uint8screen)//选择屏幕
switch(screen)
case0:
CS1=0;
CS2=0;
break;
//全屏
case1:
CS2=1;
//左半屏
case2:
CS1=1;
//右半屏
default:
voidClearScreen(uint8screen)//清屏
uint8i,j;
SelectScreen(screen);
for(i=0;
i<
8;
i++)
Set_page(i);
Set_column(0);
for(j=0;
j<
64;
j++)
write_LCD_data(0x00);
//写入0,地址指针自动加1
voidInitLCD()//LCD初始化
SelectScreen(0);
SetOnOff(0);
//关显示
SetOnOff
(1);
//开显示
ClearScreen(0);
Set_line(0);
连接开发板实物的底层应用程序:
voidLCD_Check_Busy(void)
unsignedintvalue=0,rvalue=0;
GPIO_SetDir(DATA_PORT_NUM,0x31F80000L,0);
GPIO_ClearValue(LCD_PORT_NUM,(1<
<
DI_PIN));
GPIO_SetValue(LCD_PORT_NUM,(1<
RW_PIN));
EN_PIN));
while
(1)
{
value=GPIO_ReadValue(DATA_PORT_NUM);
//获取值为32位P2.0到P2.31
/*数据位最高位D7为1内部忙,为0空闲;
对应接线为P2.22*/
rvalue=value&
0x400000;
if(0x0==rvalue)
{
break;
}
GPIO_SetDir(DATA_PORT_NUM,0x31F80000L,1);
data_setpin(0);
}
其他的函数按照上面的进行设置,其中函数GPIO_SetValue将对应的位置1,;
函数GPIO_ClearValue将对应的位置0;
函数GPIO_ReadValue获取对应端口的数据,函数GPIO_SetDir设置相应端口的相应位的方向——输入输出。
字库原理及其制作
在前面我们分析了如何点亮一个或者多个点阵,通过有意识的点亮一些点阵可以在液晶屏上看到数字、字母和汉字的显示。
那么一个字母或者汉字对应着那些位置的点阵呢,是否可以通过计算得到其字模数据?
现在可以在网上下载到各种字模软件,对单个的字符取模,也可以对ASCII码、汉字库取模生成字库bin文件。
在取模之前要对其进行相应的设置,以便能够正确的显示(当取模方式和液晶屏的设置不一样时会显示出乱码)。
需要注意的是横纵向取模的区别,字节正序和字节倒序的差别。
下面介绍字模的数据的获取,字节正序和倒序、横纵向取模的差别。
字模是一组数字,但它的意义却与数字的意义有了根本的变化,它是用数字的各位信息来记载英文或汉字的形状,如英文的'
A'
在字模的记载方式如图1所示:
8×
16的ASCII码点阵,左边的为横行取模,字节正序(即高位在前),右边的为纵向取模,字节倒序(即高位在下)。
图1“A”字模图
而中文的“你”在字模中的记载却如图2所示:
下面的取模方式只介绍了横向取模、字节正序。
如果要对其进行纵向取模、字节倒序,方法类似于“A”字模。
图2“你”字模图
当通过字模软件生成字库bin文件之后如何对其进行应用?
可以通过以下方法:
1.把字库放入SD卡中。
需要带SD卡,需要使用文件系统,软硬件成本较高。
2.把字库放入代码中一起编译,后下载到单片机中。
对单片机的FLASH要求比较大,而且代码编写调式速度比较慢。
3.购买字库IC。
不够灵活。
4.把字库放入FLASHIC中。
这种方法比较灵活,可以设置各种字体风格。
下面详细介绍将字库放入FLASHIC中的步骤。
在写入字库到FLASHIC之前,先擦除原FLASHIC中的内容,此时可以根据字库文件大小计算所需檫除扇区大小,待擦除完毕之后,开始写入bin文件,写入时采用USB传输到FLASHIC中去。
首先设置好USB相应的驱动、初始化工作,调用写数据函数。
之后download程序到单片机中,待程序运行起来之后,通过USB数据线连接FLASHIC,打开HIDDriver程序,选择bin文件,设置传输速度,开始传输。
机内码、区位码
对于英文、数字等字符的显示,由于其种类较少,只需要一个字节表示即可,ASCII码的低128专供其使用,当计算机读取字符时,其存储的8为二进制大小为其ASCII码值,同时称为字符的内码,那么其字符的字模首地址在字库中存储位置为内码乘以16。
首地址开始的16个字节数据为该字符的字模数据。
一个汉字由2个字节组成,那么其在计算机中是如何存在?
计算机中只能识别01二进制编码,而国家标准信息交换用汉字字符集GB2312-80共收录了汉字、图形符号等共7445个,其中汉字6763个,按照汉字使用的频度分为两级,其中一级汉字3755个,二级汉字3008个。
由于英文字符较少加上其他字符也不到128个,采用ASCII码的低128个表示足够,而ASCII码的高128个却很少用,因此可以采用两个高128ASCII码组合表示一个汉字。
汉字在计算机中是采用机内码的形式进行存储的,每一个汉字占2个字节,其中第一个字节为机内码的区码,汉字、各种图形符号机内码的区码范围是从0A1H(十六进制)开始,对应区位码中区码的第一区;
而机内码的第二个字节为机内码的位码,范围也是从0A1H(十六进制)开始,对应某区中的第一个位码。
就是说将汉字机内码减去0A0AH就得到该汉字的区位码。
例如汉字“北”的机内码是十六进制的“B1B1”,其中前两位“B1”表示机内码的区码,后两位“B1”表示机内码的位码。
所以“北”的区位码为0B1B1H-0A0A0H=1111H,将区码和位码分别转换为十进制,得汉字“北”的区位码为“1717”。
即“北”的点阵位于第17区的第17个字的位置,在文件HZK16中的位置为第32×
[(17-1)×
94+(17-1)]=48640D以后的32个字节为“北”的显示点阵。
用RF-1800编程器读入二进制文件hzk16j.bin后利用其编辑功能中的缓冲区编辑查找到BE00H(48640D是十进制,将其转变为十六进制后得BE00H)开始的32个字节:
048004800488049804A07CC00480048004800480048004801C82E482447E0000(以上全为十六进制),将其写在16×
16点阵方格纸上。
汉字、图形符号根据其位置将其分为94个“区”,每个区包含94个汉字字符,每个汉字字符又称为“位”。
其中“区”的序号由01区至94区,“位”的序号也由01位至94位。
若以横向表示“位”号,纵向表示“区”号,则“区”和“位”构成一个二维坐标。
给定一个“区”值和“位”值就可以确定一个惟一的汉字或图形符号。
即4位阿拉伯数字就可以惟一地确定一个汉字或符号。
如“北”字的区位码是“1717”(区位码是十进制表示,机内码是十六进制表示)。
前两位是“区”号,后两位是“位”号。
其中1至15区是各种图形符号、制表符和一些主要国家的语言字母,16区至87区是汉字,其中16区至55区是一级汉字,56至87区是二级汉字。
那么计算机是如何识别汉字和ASCII字符呢?
当其读到的ASCII码值大于0A1H时,先暂不处理而是继续读取下一字节,如果也是大于0A1H时,则识别为汉字或者图形符号,两个合起来组成机内码。
计算机读取一个汉字的机内码时,先将其转换为区位码(第一个字节减去0B1H,得到区码;
第二节字节也减去0B1H,得到位码),再根据区位码计算该汉字字模在字库中的存储首地址(计算公式为32×
[(区码-1)×
94+(位码-1)])。
分别读取其后的32个字节数据在液晶屏相应位置点亮其点阵,从而得到我们想要的效果。
GUI图形用户界面
GUI为GraphicsUserInterface的缩写,即图形用户界面,已经广泛的应用于嵌入式产品中。
通过窗口、图标和菜单等图形界面方便快捷的实现人机交互功能。
移植GUI到LCD12864液晶上,我们采用的是ZLG/GUI(周立功开发的)。
里面提供一些基本图形操作、颜色转换、ASCII码和汉字显示、菜单和窗口操作函数等等。
ZLG/GUI可以分为三个层次,第一层为硬件驱动层,也即是底层驱动。
它主要负责硬件驱动,将显示数据转换并发送给图形显示设备。
第二层为基本图形层。
它提供一些基本的作图功能,如画线、圆形、矩形和椭圆等。
第三层为高级接口层。
主要是在基本绘图之上为用户提供窗口、图标和菜单等图形接口。
移植过程中我们主要是针对底层驱动的基本函数进行修改,在驱动头文件中根据实际液晶屏的大小设置X,Y轴的大小,定义相应的操作地址(主要用于写命令和数据),设置相应操作命令字的宏定义。
在驱动源文件中根据液晶屏大小修改缓冲区大小。
由于前面已经介绍过LCD12864液晶基本显示原理,因此可以直接采用其中的驱动设置,完成基本的读写命令和数据的功能,然后调用GUI的上层函数实现窗口、菜单等复杂功能。
在ZLG/GUI中主要是针对横向字节正序字模的显示设置,高位在前,因此其字节设置如下uint8constDCB_HEX_TAB[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
而在我们所采用的LCd12864中主要是纵向字节倒序,高位在下,因此其字节设置为uint8constDCB_HEX_TAB[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
同时应注意X轴的八位组成一个字节应改为Y轴的八位构成一个字节。
在编写画线函数时应分四种情况考虑,水平线,垂直线,X轴增长较大的斜线,Y轴增长较大的斜线。
在绘画直线时应注意覆盖的问题,对于垂直线,由于我们采用的12864LCD是纵轴8位组成一个字节,而对于水平线,直接画线,这样直线上下原有的内容会被覆盖。
为了避免这个问题,我们在对数据进行操作时要先读取原位置上的数据,然后对其做或运算,这样可以在不破换原数据图形的基础上绘画我们想要的直线。
其他斜线的绘画也应考虑相同的问题。
由前面的介绍可知,我们定义P1口作为数据口,总共有32位,而我们只连接其中的八位进行数据的输入输出。
而我们采用GPIO_ReadValue函数可以获得P1口的数据,但是为32为数据,对于我们有用的是上面定义的8位,通过移位操作(主要高地位)得到正确的原液晶显示数据。
同理,写入数据到LCD的方式也是一样的,根据数据位的01状态分别设置LCD点阵的开关。
知识要点与技巧
1.开辟缓冲区,更快的显示图形
在没有移植ZLG/GUI到12864LCD上时,都是直接在液晶屏上进行显示操作,显示出来的效果和采用GUI时一样的,但是从显示速度上来看,相差太远,直接绘画水平线,需要逐点的绘画,由于其读/写操作速度较慢会使显示速度很慢。
而在RAM中开辟一块显示缓冲区缓冲区,大小一般与实际图形显示设备的点像素对应,如128×
64点的单色图形LCD开辟显示缓冲区大小为1024字节(即128×
64/8一字节数据对应8个点像素)。
在RAM开辟显示缓冲区进行图形操作时可以获得较高的速度,待操作完毕后再将显示缓冲区的数据发送到显示设备中。
在RAM中建立显示缓冲区画图操作先对显示缓冲区相应点的数据进行设置然后控制数据输出更新LCD显示保证LCD显示及缓冲区数据同步(注意显示缓冲区只有硬件驱动层使用)
2.注意操作符优先级
在调用ZLG/GUI进行图形绘画时,有个地方不能正确显示,通过逐步调试发现i*3+j>
>
3应该写成i*3+(j>
3),因为“>
”的优先级小于“+”,通过对其修改,可以在液晶屏上输入正确的结果。