LCD1602显示器
作者:姜蘅洋
1.LCD1602介绍:
- LCD1602是一个LCD的显示器:
- LCD的英文:Liquid Crystal Display,即液晶显示器。
- LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。
- 每个字符位由一个5 x 8的点阵组成,通过点阵的亮灭组合形成字符。
- 其中,1602表示该显示器的分辨率是16 x 2,即每行显示16个字符,一共可以显示两行字符。
- 每个字符位之间有一定的间隔,两行之间也有一定的间隔。
- LCD1602的工作环境:
- 工作电压:4.5~5V
- 工作电流:2.0mA
- 工作温度:-20°C~70°C
- LCD1602的引脚说明:
- 16Pin:
- 固定引脚:
- Pin_1:VSS电源地。
- Pin_2:VDD电源正极。
- Pin_15:BLA背光源正极。
- Pin_16:BLK背光源负极。
- 配置引脚:
- VL:液晶显示偏压信号。
- 调整LCD1602的显示对比度,引脚电压为0时可以得到最高的对比度。
- RS:数据命令选择端。
- RS = 1的时候,输入字节当做数据处理。
- RS = 0的时候,输入字节当做命令处理。
- R/W:读写选择端。
- 当R/W = 1的时候,执行读操作,即单片机从LCD1602中读数据。
- 当R/W = 0的时候,执行写操作,即单片机向LCD1602中写数据。
- LCD1602固定执行显示功能:
- 我们只需要让LCD1602显示字符,即向LCD1602中写入数据,不需要从LCD1602中读取数据。
- LCD1602固定执行显示功能:
- E:使能信号。
- 本质上来讲是LCD1602 的数据控制时钟信号。
- D0 ~ D7:数据字节或命令字节。
- 8 位并行数据口。
- VL:液晶显示偏压信号。
2.LCD1602的驱动程序:
单片机驱动程序:
- 在单片机领域,外设驱动程序是指单片机控制操作外部设备的软件组件。
- 驱动程序定义了单片机和外设的通信方式(也就是时序问题)。
- 在单片机领域,外设驱动程序是指单片机控制操作外部设备的软件组件。
根据外设时序图编写外设驱动程序:
写时序:以写命令字节为例。
写数据的时候只需要把RS置为高电平即可。
由于是写命令,因此在整个写时序中:
- 把RS设置为0,即输入字节当做命令处理。
- 把R/W设置为0,即执行写入操作。
相应的我们只需要考虑E和D的时序:
标点:开始点、转折点、结束点
时序参数:
A点:E = 0,A点和B点之间没有信号更改,不需要延时。
B点:B点数据载入寄存器,B点和C点之间有一个跳变延时,对于这种跳变,我们不需要延时。
C点:数据载入完成,C点和D点之间有一个
的延时,由于该延时的最小值是40ns,没有最大值限制,由于我们的单片机是us级别(周期是90us左右)的,因此延时设置10us即可。10us延时的原因是:STC-ISP计时软件能生成最小的延时函数是10us,当然STC89C52的机器周期是1us(对应的频率是1MHz)。
- c
void LCD_DriverDelay() //@11.0592MHz { unsigned char data i; i = 2; while (--i); }
1
2
3
4
5
6
7
D点:E = 1,同时D点和E点之间有一个延时
,这个延时没有最小值限制,因此不延时。E点:信号线E到达高电平,即开始稳定的发送数据,E点和F点之间的延时
的最小值是150ns,这里我们设置10us。F点:E = 0,同时F点和G点之间有一个延时
,这个延时没有最小值限制,因此不延时。G点:信号线E到达低电平,G点和H点之间有一个延时
,这个延时的最小值是20ns,这里我们设置为10us。H点:一个写时序周期完成,后面的点是下一个写时序的点。
查看原理图:
驱动代码:
- c
void LCD1602_Write_Command(uint_8 command) { RS = 0; WR = 0; LCD_EN = 0; Write_Byte = command; LCD_WriteDriverDelay_10us(); LCD_EN = 1; LCD_WriteDriverDelay_10us(); LCD_EN = 0; LCD_WriteDriverDelay_10us(); }
1
2
3
4
5
6
7
8
9
10
11
12 该代码和上面的分析完全对应。
初始化:
- 我们在使用外设之前,必须要初始化。
- 初始化LCD1602的时序说明:
显示模式设置指令:
- 0x38:设置16 x 2显示,5 x 7点阵,8位数据接口。
显示清屏:
- 0x01:数据地址指针清0,所有显示清0。
显示回车:
- 0x02:数据地址指针清0。
显示光标移动设置:
- 0x04:写一个字符后,地址指针减1,且光标减1,整屏显示不移动。
- 0x05:写一个字符后,地址指针减1,且光标减1,整屏显示右移。
- 0x06:写一个字符后,地址指针加1,且光标加1,整屏显示不移动。
- 0x07:写一个字符后,地址指针加1,且光标加1,整屏显示左移。
显示开关及光标位置:
- 0x08:显示关闭。
- 0x0F:显示光标并且光标闪烁。
- 0x0E:显示光标但光标不闪烁。
- 0xC0:不显示光标。
- 这里还要注意,由于P0端口复用,因此我们要失能控制数码管的74HC573的Latch Enable:
初始化代码:
- c
void LCD1602_Init(void) { DULA=0; WELA=0; LCD1602_Write_Command(0x38); LCD_InitDriverDelay_5ms(); LCD1602_Write_Command(0x0C); LCD_InitDriverDelay_5ms(); LCD1602_Write_Command(0x06); LCD_InitDriverDelay_5ms(); LCD1602_Write_Command(0x01); LCD_InitDriverDelay_5ms(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
显示字符:
- LCD1602控制器内部带有80字节的RAM缓冲区,每个字节存储的值用来使点阵屏显示字符。
- 对应关系:
- 多出来的字节:
- 正常来讲,对于16 x 2的LCD屏,有32个字节即可。
- 多出来的字节的目的是满足上面不同的显示光标移动设置。
- 多出来的字节:
- 对应关系:
- LCD1602控制器内部有一个数据地址指针,可以通过这个指针访问全部的80字节RAM。
- 例如:
- 指令码是0x80,那么数据地址指针指代的就是第一行第一列,接下来我们向这个点阵中写入字符。
- 指令码是0x80 + 0x40,那么数据地址指针指代的就是第一行第二列,接下来我们向这个点阵中写入字符。
- 我们不用每写入一个字符就手动改变数据地址指针的位置,在显示光标移动设置中会设置自动改变数据地址指针的位置。
- 例如:
- LCD1602控制器内部带有80字节的RAM缓冲区,每个字节存储的值用来使点阵屏显示字符。
字符表:
- 标准字符表符合ASCII编码。
3.LCD1602实验:
- c
//lcd1602.h #ifndef __LCD1602_H__ #define __LCD1602_H__ #include "overwhelm.h" #include <intrins.h> #define RS P3_5 #define WR P3_6 #define LCD_EN P3_4 #define DULA P2_6 #define WELA P2_7 #define Write_Byte P0 void LCD_Write_Line(uint_8 Command,uint_8 *str); void LCD1602_Init(void); #endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14 - c
//lcd1602.c #include "lcd1602.h" void LCD_WriteDriverDelay_10us() //@11.0592MHz { unsigned char data i; i = 2; while (--i); } void LCD_InitDriverDelay_5ms(void) //@11.0592MHz { unsigned char data i, j; i = 9; j = 244; do { while (--j); } while (--i); } void LCD1602_Write_Command(uint_8 command) { RS = 0; WR = 0; LCD_EN = 0; Write_Byte = command; LCD_WriteDriverDelay_10us(); LCD_EN = 1; LCD_WriteDriverDelay_10us(); LCD_EN = 0; LCD_WriteDriverDelay_10us(); } void LCD1602_Write_Data(uint_8 dat) { RS = 1; WR = 0; LCD_EN = 0; Write_Byte = dat; LCD_WriteDriverDelay_10us(); LCD_EN = 1; LCD_WriteDriverDelay_10us(); LCD_EN = 0; LCD_WriteDriverDelay_10us(); } void LCD1602_Init(void) { DULA=0; WELA=0; LCD1602_Write_Command(0x38); LCD_InitDriverDelay_5ms(); LCD1602_Write_Command(0x0C); LCD_InitDriverDelay_5ms(); LCD1602_Write_Command(0x06); LCD_InitDriverDelay_5ms(); LCD1602_Write_Command(0x01); LCD_InitDriverDelay_5ms(); } void LCD_Write_Line(uint_8 Command,uint_8 *str) { LCD1602_Write_Command(Command); while (*str != '\0') { LCD1602_Write_Data(*str++); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 - c
//main.c #include "overwhelm.h" uint_8 First_lineString[] = " CCNU-IOT "; uint_8 Second_lineString[] = " We Welcome you!"; void main(void) { LCD1602_Init(); LCD_Write_Line(0x80,First_lineString); LCD_Write_Line(0x80 + 0x40,Second_lineString); while (1) { } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14 实验结果: