LCD1602液晶显示屏
# LED1602液晶显示屏
- LCD1602(Liquid Crystal Display)液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置特殊字符,还可以有8个自定义字符
- 显示容量:16×2个字符,每个字符为5*7点阵
# 一、引脚定义
引脚定义其实比较简单,我们重点来介绍一下RS、RW和E这三个引脚。
- RS:用来选择发送的是指令还是数据,高电平就是发送数据,低电平就是发送指令。
- RW:用来选择是读还是写,高电平为读,低电平为写。
- E: 高电平为数据有效,低电平为执行操作。
- 分别对应的引脚如上
引脚 | 功能 |
---|---|
VSS | 地 |
VDD | 电源正极(4.5~5.5V) |
VO | 对比度调节电压 |
RS | 数据/指令选择,1为数据,0为指令 |
RW | 读/写选择,1为读,0为写 |
E | 使能,1为数据有效,下降沿执行命令 |
D0~D7 | 数据输入/输出 |
A | 背光灯电源正极 |
K | 背光灯电源负极 |
# 二、内部结构
LCD1602的内部结构大体如下所示:左边是我们的控制器,其中AC(光标位置)我们在后面会用到,相当于选地址的一个功能。然后右边是DDRAM(数据显示区),我们就是把数据写入到这个地方,然后通过字模库,将其转换为显示在屏幕上面的数字。
# 1、DDRAM(数据显示区)
- DDRAM就是我们需要写入数据的地址,需要注意的是,第二行是从0x40开始的。
- 注意,DDRAM显示位置有40列,但是我们的屏幕只有16列,可以用指令让屏幕左/右移,实现屏幕滚动
# 2、字模库
- 这个就是字符码与字模的关系 ,比如1对应的是00110001,以此类推。并且与我们的ASCII是有着对应关系的。
# 三、时序结构
- 其实就是我们之前介绍的,写入数据和写入指令。 RS选择写入数据或者是选择指令,然后选择写入数据,然后E赋能,DB写入我们需要的数据,就好了。
# 四、指令集
# 五、操作流程
# 1、初始化
发送指令0x38 | 八位数据接口,两行显示,5*7点阵 |
---|---|
发送指令0x0C | 显示开,光标关,闪烁关 |
发送指令0x06 | 数据读写操作后,光标自动加一,画面不动 |
发送指令0x01 | 清屏 |
# 2、显示字符
发送指令0x80|AC | 设置光标位置 |
---|---|
发送数据 | 发送要显示的字符数据 |
发送数据 | 发送要显示的字符数据 |
# 六、代码
- LCD1602.c
#include <REGX52.H>
#include <INTRINS.H>
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
#define LCD_DataPort P0
//函数定义:
/**
* @brief LCD1602延时函数,1ms
* @param 无
* @retval 无
*/
void LCD_Delay() //@11.0592MHz,1ms
{
unsigned char i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0; //选择为指令(0),1为数据
LCD_RW=0; //选择为写(0),1为读
LCD_DataPort = Command;
LCD_E=1;
LCD_Delay(); //E的脉冲时间太快,模块指令相对其较慢,所以E有高低变换时必须给延迟,防止指令读取失败
LCD_E=0;
LCD_Delay();
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Date)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Date;
LCD_E=1;
LCD_Delay(); //E的脉冲时间太快,模块指令相对其较慢,所以E有高低变换时必须给延迟,防止指令读取失败
LCD_E=0;
LCD_Delay();
}
void LCD_Init()
{
LCD_WriteCommand(0x38); //八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0C); //显示开,光标关,闪烁关
LCD_WriteCommand(0x06); //数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01); //清屏
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置开始显示所给字符串
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
//这里之所以不断执行写入数据操作而不用往后改变位置,是因为我们初始化里设置了数据读写操作后,光标自动加一,画面不动
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/**
* @brief 在LCD1602指定位置开始显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~65535
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i)%10+'0');//根据ASCII表知。加上0x30(符号0)才能显示数字
}
}
/**
* @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-32768~32767
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;// 防止不能显示-32768
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFF
* @param Length 要显示数字的长度,范围:1~4
* @retval 无
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
//根据ASCII表知。加上0x30(符号'A')才能显示数字
LCD_WriteData(SingleNumber-10+'A');// 十六进制需要表示字符
}
}
}
/**
* @brief 在LCD1602指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
- main.c
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
void main()
{
LCD_Init(); //LCD初始化
LCD_ShowChar(1,1,'A'); //在1行1列显示字符A
LCD_ShowString(1,3,"Hello"); //在1行3列显示字符串Hello
LCD_ShowNum(1,9,66,2); //在1行9列显示数字66,长度为2
LCD_ShowSignedNum(1,12,-88,2); //在1行12列显示有符号数字-88,长度为2
LCD_ShowHexNum(2,1,0xA5,2); //在2行1列显示十六进制数字0xA5,长度为2
LCD_ShowBinNum(2,4,0xA5,8); //在2行4列显示二进制数字0xA5,长度为8
LCD_ShowChar(2,13,0xDF); //在2行13列显示编码为0xDF的字符
LCD_ShowChar(2,14,'C'); //在2行14列显示字符C
LCD_ShowString(1,16,"Meursault639");
while(1)
{
LCD_WriteCommand(0x18); //画面向左移位,光标不动
Delay(1000);
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
编辑 (opens new window)
上次更新: 2023/09/13, 12:29:52