您的位置 首页 知识

lcd1602程序(【嵌入式开发必看】详解液晶显示器LCD1602显示器介绍与编程技巧(包含源程序例程))

lcd1602程序
液晶屏概述:

液晶显示屏中,1602型算是比较简单的一种,据说和12864还是全兼容的。
1602里的存储器有三种:CGROM、CGRAM、DDRAM。CGROM保存了厂家生产时固化在LCM中的点阵型显示数据,CGRAM是留给用户自己定义点阵型显示数据的,DDRAM则是和显示屏的内容对应的。1602内部的DDRAM有80字节,而显示屏上只有2行×16列,共32个字符,所以两者不完全一一对应。默认情况下,显示屏上第一行的内容对应DDRAM中80H到8FH的内容,第二行的内容对应DDRAM中CH到CFH的内容。DDRAM中90H到A7H、D0H到E7H的内容是不显示在显示屏上的,但是在滚动屏幕的情况下,这些内容就可能被滚动显示出来了。注:这里列举的DDRAM的地址准确来说应该是DDRAM地址+80H之后的值,因为在向数据总线写数据的时候,命令字的最高位总是为1。
1602使用三条控制线:EN、RW、RS。其中EN起到类似片选和时钟线的作用,RW和RS指示了读、写的方向和内容。在读数据(或者Busy标志)期间,EN线必须保持高电平;而在写指令(或者数据)过程中,EN线上必须送出一个正脉冲。RW、RS的组合一共有四种情况,分别对应四种操作:RS=0、RW=0——表示向LCM写入指令RS=0、RW=1——表示读取Busy标志RS=1、RW=0——表示向LCM写入数据RS=1、RW=1——表示从LCM读取数据。
LCD在使用的过程中,可以在RS=0、RW=0的情况下,向LCM写入一个字节的控制指令。使用的控制指令一共八个类别。有的类别又有几条不同的指令。具体的情况罗列在下:①01H:清除DDRAM的所有单元,光标被移动到屏幕左上角。②02H:DDRAM所有单元的内容不变,光标移至左上角。③输入方式设置(EnterModeSet),这些指令规定了两个方面:一是写入一个DDRAM单元后,地址指针如何改变(加一还是减一);二是屏幕上的内容是否滚动。04H:写入DDRAM后,地址指针减一,比如第一个字符写入8FH,则下一个字符会写入8EH;屏幕上的内容不滚动。05H:写入DDRAM后,地址指针减一,同上一种情况;每一个字符写入以后,屏幕上的内容向右滚动一个字符位。06H:写入DDRAM后,地址指针加一,比如第一个字符写入80H,则下一个字符会写入81H;屏幕上的内容也是不滚动。这应该是最常用的一种显示方式。07H:写入DDRAM后,地址指针加一,同上一种情况;每一个字符写入以后,屏幕上的内容向左滚动一个字符位。④屏幕开关、光标开关、闪烁开关。

08H、09H、0AH、0BH:关闭显示屏,实质上是不把DDRAM中的内容对应显示在屏幕上,对DDRAM的操作还是在进行的,执行这条指令,接着对DDRAM进行写入,屏幕上没有任何内容,但是接着执行下面的某条指令,就能看到刚才屏幕关闭期间,对DDRAM操作的效果了。0cH:打开显示屏,不显示光标,光标所在位置的字符不闪烁。0dH:打开显示屏,不显示光标,光标所在位置的字符闪烁。0eH:打开显示屏,显示光标,光标所在位置的字符不闪烁。0fH:打开显示屏,显示光标,光标所在位置的字符闪烁。关于光标的位置:光标所在的位置指示了下一个被写入的字符所处的位置,加入在写入下一个字符前没有通过指令设置DDRAM的地址,那么这个字符就应该显示在光标指定的地方。⑤设置光标移动(本质就是AC的增加还是减少)、整体画面是否滚动。10H:每输入一次该指令,AC就减一,对应了光标向左移动一格。整体的画面不滚动。14H:每输入一次该指令,AC就加一,对应了光标向右移动一格。整体的画面不滚动。18H:每输入一次该指令,整体的画面就向左滚动一个字符位。

1CH:每输入一次该指令,整体的画面就向右滚动一个字符位。画面在滚动的时候,每行的首尾是连在一起的,也就是每行的第一个字符,若左移25次,就会显示在该行的最后一格。在画面滚动的过程中,AC的值也是变化的。⑥显示模式设定指令,设定了显示几行,显示什么样的点阵字符,数据总线占用几位。20H:4位总线,单行显示,显示5×7的点阵字符。24H:4位总线,单行显示,显示5×10的点阵字符。28H:4位总线,双行显示,显示5×7的点阵字符。2CH:4位总线,双行显示,显示5×10的点阵字符。30H:8位总线,单行显示,显示5×7的点阵字符。34H:8位总线,单行显示,显示5×10的点阵字符。38H:8位总线,双行显示,显示5×7的点阵字符。这是最常用的一种模式。3CH:8位总线,双行显示,显示5×10的点阵字符。
一.接口
一般来说,LCD1602有16条引脚,据说还有14条引脚的,与16脚的相比缺少了背光电源A(15脚)和地线K(16脚)。我手里这块LCD1602的型号是HJ1602A,是绘晶科技公司的产品,它有16条引脚。如图1所示:

再来一张它的背面的,如图2所示:

它的16条引脚定义如下:
1. VSS接电源地。
3. VO是液晶显示的偏压信号,可接10K的3296精密电位器。或同样阻值的RM065/RM063蓝白可调电阻。见图3。

4. RS是命令/数据选择引脚,接单片机的一个I/O,当RS为低电平时,选择命令;当RS为高电平时,选择数据。
6. E,执行命令的使能引脚,接单片机的一个I/O。
8. A背光正极,可接一个10—47欧的限流电阻到VDD。

二.基本操作
1. 读状态:输入RS=0,RW=1,E=高脉冲。输出:D0—D7为状态字。
3. 写命令:输入RS=0,RW=0,E=高脉冲。输出:无。
读操作时序图(如图5):

写操作时序图(如图6):

时序时间参数(如图7):

三.DDRAM、CGROM和CGRAM

DDRAM相当于计算机的显存,我们为了在屏幕上显示字符,就把字符代码送入显存,这样该字符就可以显示在屏幕上了。同样LCD1602共有80个字节的显存,即DDRAM。但LCD1602的显示屏幕只有16×2大小,因此,并不是所有写入DDRAM的字符代码都能在屏幕上显示出来,只有写在上图所示范围内的字符才可以显示出来,写在范围外的字符不能显示出来。这样,我们在程序中可以利用下面的“光标或显示移动指令”使字符慢慢移动到可见的显示范围内,看到字符的移动效果。

上图的左边就是字符‘A’的字模数据,右边就是将左边数据用“○”代表0,用“■”代表1。从而显示出‘A’这个字形。从下面的图可以看出,字符‘A’的高4位是0100,低4位是0001,合在一起就是01000001b,即41H。它恰好与该字符的ASCII码一致,这样就给了我们很大的方便,我们可以在PC上使用P2=‘A’这样的语法。编译后,正好是这个字符的字符代码。

上面这个图(如图10)说明的是5×8点阵和5×10点阵字符的字形和光标的位置。先来说5×8点阵,它有8行5列。那么定义这样一个字符需要8个字节,每个字节的前3个位没有被使用。例如,定义摄氏温标的符号{0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00}。

上面这个图(如图11)说明的是设置CGRAM地址指令。从这个指令的格式中我们可以看出,它共有aaaaaa这6位,一共可以表示64个地址,即64个字节。一个5×8点阵字符共占用8个字节,那么这64个字节一共可以自定义8个字符。也就是说,上面这个图的6位地址中的DB5DB4DB3用来表示8个自定义的字符,DB2DB1DB0用来表示每个字符的8个字节。这DB5DB4DB3所表示的8个自定义字符(0–7)就是要写入DDRAM中的字符代码。我们知道,在CGRAM中只能定义8个自定义字符,也就是只有0—7这8个字符代码,但在下面的这个表(如图12)中一共有16个字符代码(××××0000b–××××1111b)。实际上,如图所示,它只能表示8个自定义字符 (××××0000b=××××1000b, ××××0001b=××××1001b……依次类推)。也就是说,写入DDRAM中的字符代码0和字符代码8是同一个自定义字符。 5×10点阵每个字符共占用16个字节的空间,所以CGRAM中只能定义4个这样的自定义字符。

四.LCD1602指令

×:不关心,也就是说这个位是0或1都可以,一般取0。
DL=1:8位数据接口(D7—D0)。
N=0:一行显示。
F=0:5×8点阵字符。
说明:因为是写指令字,所以RS和RW都是0。LCD1602只能用并行方式驱动,不能用串行方式驱动。而并行方式又可以选择8位数据接口或4位数据接口。这里我们选择8位数据接口(D7—D0)。我们的设置是8位数据接口,两行显示,5×8点阵,即0b00111000也就是0x38。(注意:NF是10或11的效果是一样的,都是两行5×8点阵。因为它不能以两行5×10点阵方式进行显示,换句话说,这里用0x38或0x3c是一样的)。

D=1:显示开,D=0:显示关。
B=1:光标闪烁,B=0:光标不闪烁。
3.进入模式设置指令(如图15、16)

I/D=1:写入新数据后光标右移。
S=1:显示移动。

说明:这里的设置是0x06。

说明:在需要进行整屏移动时,这个指令非常有用,可以实现屏幕的滚动显示效果。初始化时不使用这个指令。

说明:清除屏幕显示内容。光标返回屏幕左上角。执行这个指令时需要一定时间。

说明:光标返回屏幕左上角,它不改变屏幕显示内容。

说明:这个指令在上面已经介绍过。用法在后面例子中说明。

说明:这个指令用于设置DDRAM地址。在对DDRAM进行读写之前,首先要设置DDRAM地址,然后才能进行读写。前面我们说过,DDRAM就是LCD1602的显示存储器。我们要在它上面进行显示,就要把要显示的字符写入DDRAM。同样,我们想知道DDRAM某个地址上有什么字符,也要先设置DDRAM地址,然后将它读出到单片机。

说明:这个指令用来读取LCD1602状态。对于单片机来说,LCD1602属于慢速设备。当单片机向其发送一个指令后,它将去执行这个指令。这时如果单片机再次发送下一条指令,由于LCD1602速度较慢,前一条指令还未执行完毕,它将不接受这新的指令,导致新的指令丢失。因此这条读忙指令可以用来判断LCD1602是否忙,能否接收单片机发来的指令。当BF=1,表示LCD1602正忙,不能接受单片机的指令;当BF=0,表示LCD1602空闲,可以接收单片机的指令。RS=0,表示是指令;RW=1,表示是读取。这条指令还有一个副产品:即可以得到地址记数器AC的值(address counter)。LCD1602维护了一个地址计数器AC,用来记录下一次读写CGRAM或DDRAM的位置。需要强调的是:这条指令我一次也没有执行成功。很多网友似乎也是这样。好在我们有另外的办法,也就是延时。通过查看每条指令的执行时间,再经过一些试验,可以确定指令的延时。这样就可以在上一条指令执行完毕后再执行下一条指令了。

说明:RS=1,数据;RW=0,写。指令执行时,要在DB7—DB0上先设置好要写入的数据,然后执行写命令。

说明:RS=1,数据;RW=1,读。先设置好CGRAM或DDRAM的地址,然后执行读取命令。数据就被读入后DB7—DB0。
1602液晶屏常用指令集
1602通过D0~D7的8位数据端传输数据和指令。
显示模式设置:(初始化)
0011 1000[0x38]设置16×2显示,5×8点阵,8位数据接口;
显示开关及光标设置:(初始化)
0000 1DCB D显示(1有效)、C光标显示(1有效)、B光标闪烁(1有效)
0000 01NS N=1(读或写一个字符后地址指针加1 &光标加1),
N=0(读或写一个字符后地址指针减1 &光标减1),
S=1 且 N=1 (当写一个字符后,整屏显示左移)
s=0 当写一个字符后,整屏显示不移动
数据指针设置:
数据首地址为80H,所以数据地址为80H+地址码(0-27H,40-67H)
其他设置:
01H(显示清屏,数据指针=0,所有显示=0);02H(显示回车,数据指针=0)。
通常推荐的初始化过程:
延时15ms
写指令38H
延时5ms
写指令38H
延时5ms
写指令38H
延时5ms
(以上都不检测忙信号)
(以下都要检测忙信号)
写指令38H
写指令08H 关闭显示
写指令01H 显示清屏
写指令06H光标移动设置
写指令0cH 显示开及光标设置
完毕
下面我们就以一个实例来结束这篇文章。先介绍一下背景:单片机最小系统(扩充了外部RAM 62256)。采用STC89C52RC,晶振22.1184MHZ。以5×8点阵,16×2行,8位数据端口。首先在第一行显示“I love MCU!”,第二行显示“LCD1602 Test!”。延时一段时间,清屏。然后在第一行显示自定义字符:摄氏温标标志。第二行显示圆周率(pai)标志。再延时一段时间,清屏。最后在第一行显示“Welcome to my blog!”,显示方式是从屏幕右面移入,左面移出。周而复始(如图26)。

#ifndef __ZHANGTYPE_H__
#define uint8 unsigned char
#define uint32 unsigned long int
#define int16 signed short int
#define uint64 unsigned long long int
#ifndef __FUN_H__
#include ‘ZhangType.h’
void Delay(uint16 time)
{
}
#define __1602_H__
#include ‘fun.h’ //常用函数
#define DISOPEN 0x0C //显示开,不显示光标,光标不闪烁
#define SETADDR 0x80 //设置数据地址指针初始值
#define RET 0x02 //回车,数据指针清零
sbit RS = P1^0;
sbit E = P1^2;
void Write1602_Com(uint8 com); //写命令
void CheckBusy(void); //检查忙
void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf); //写一个数据串
void Write1602_Com(uint8 com)
{
RS=0; //命令
RW=0; //写
PORT=com; //端口赋值
E=1; //高脉冲
E=0;
}
{
RS=1; //数据
RW=0; //写
PORT=dat; //端口赋值
E=1; //高脉冲
E=0;
void CheckBusy(void)
{
RS=0; //命令
E=0;
}
{
E=1; //高脉冲
E=0;
break;
void Init1602(void);
{
Delay(500);
Delay(500);
Delay(500);
Delay(500);
void Write1602_One_Dat(uint8 x,uint8 y,uint8 dat)
x&=0x0f;
if(y)
x|=0x80;
Write1602_Dat(dat);
void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf)
{
Write1602_Com(addr);
/*******************************************************
*功能:测试显示
#include ‘1602.h’
uint8 code hot[8]={ //摄氏温度字模
uint8 code pi[8]={
};
uint8 code strTest[]=’LCD1602 Test!’;
uint8 i;
{
//自定义CGRAM
Write1602_Str(0x48,8,pi); //pai
Write1602_Str(0x80+0x40,strlen(strTest),strTest); //’LCD1602 Test!’
Delay(10000);
Delay(500); //多加一些延时
Write1602_Dat(0);
for(i=0;i<16;i++)
for(i=0;i<50;i++) //延时一段时间
Write1602_Com(CLEAR); //指令执行时间较长
Write1602_Str(0x80+0x10,strlen(blog),blog); //写在显示之外
{
for(i=0;i<20;i++) //延时
}
}
我们官方的QQ群1:281549832
我们官方的QQ群2:386393398
我们的开源团队不断扩大,希望大家快来一起加入我们吧。
在这里还是要谢谢大家的大力支持!如有任何问题可以咨询我们。
请大家记得转发出去,让跟多的人去学习开发技术。谢谢大家支持!
单片机实例已经通过STC89C52RC验证通过,大家直接可以使用。

lcd1602程序相关文章


返回顶部