非标协议外设

LCD1602显示

概述

LCD1602(Liquid Crystal Display)是一种工业字符型液晶,能够同时显示 16×02 即 32 字符(16列两行)

image-20220705221821632

引脚说明

image-20220705221824828

第 1 脚: VSS 为电源地 第 2 脚: VDD 接 5V 正电源 第 3 脚: VL 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个 10K 的电位器调整对比度。 第 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。 第 5 脚:R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W 共同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电平时可以读忙信号,当 RS 为高电平 R/W 为低电平时可以写入数据。 第 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。 第 7-14 脚:D0~D7 为 8 位双向数据线。 第 15 脚:背光源正极。 第 16 脚:背光源负极。

接线表

LCD1602 单片机
VSS GND
VDD 5V
VO GND
RS P1.0
RW P1.1
E P1.2
A 5V
K GND
D0~D7 P0.0~Po.7

LCD1602指令

image-20220705222932571

开发逻辑

image-20220705222947558

例如第二行第一个字符的地址是 40H,那么是否直接写入 40H 就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7 恒定为高电平 1 所以实际写入的数据应该是01000000B(40H) +10000000B(80H)=11000000B(C0H)

显示什么

image-20220705223032600

读写操作时序

读操作时序
image-20220705223114577
写操作时序
image-20220705223129166
数序参数
image-20220705223144533

显示一个字符C

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
#include "reg52.h"
#include "intrins.h"
/*RS -- P1.0
RW -- P1.1
E -- P1.2 */
#define databuffer P0 //定义8位数据线,Po端口组
sbit RS = P1 ^ 0;
sbit RW = P1 ^ 1;
sbit EN = P1 ^ 2;
void check_busy()
{
char tmp = 0x80;
databuffer = 0x80;
while (tmp & 0x80)
{ // 1000 0000
RS = 0;
RW = 1;
EN = 0;
_nop_();
EN = 1;
_nop_();
_nop_();
tmp = databuffer;
EN = 0;
_nop_();
}
}
void Write_Cmd_Func(char cmd)
{
check_busy();
RS = 0;
RW = 0;
EN = 0;
_nop_();
databuffer = cmd;
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
void Write_Data_Func(char dataShow)
{
check_busy();
RS = 1;
RW = 0;
EN = 0;
_nop_();
databuffer = dataShow;
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
void Delay15ms() //@11.0592MHz
{
unsigned char i,
j;
i = 27;
j = 226;
do
{
while (--j)
;
} while (--i);
}
void Delay5ms() //@11.0592MHz
{
unsigned char i,
j;
i = 9;
j = 244;
do
{
while (--j)
;
} while (--i);
}
void LCD1602_INIT()
{
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
Write_Cmd_Func(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
//(5)写指令 38H:显示模式设置
Write_Cmd_Func(0x38);
//(6)写指令 08H:显示关闭
Write_Cmd_Func(0x08);
//(7)写指令 01H:显示清屏
Write_Cmd_Func(0x01);
//(8)写指令 06H:显示光标移动设置
Write_Cmd_Func(0x06);
//(9)写指令 0CH:显示开及光标设置}
Write_Cmd_Func(0x0c);
}
void main()
{
char position = 0x80 + 0x05;
char dataShow = 'C';
LCD1602_INIT();
Write_Cmd_Func(position);
//选择要显示的地址
Write_Data_Func(dataShow);
//发送要显示的字符
}
IMG_4517

这里的电位器 用于调整对比度

也就是V0 引脚 当v0 为5v的时候对比度最大 啥也看不见

当V0为GND 的时候 对比度最小 可以看见 但是有方块

显示一行文字

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
#include "reg52.h"
#include "intrins.h"
/*RS -- P1.0
RW -- P1.1
E -- P1.2 */
#define databuffer P0 //定义8位数据线,Po端口组
sbit RS = P1 ^ 0;
sbit RW = P1 ^ 1;
sbit EN = P1 ^ 2;
void check_busy()
{
char tmp = 0x80;
databuffer = 0x80;
while (tmp & 0x80)
{ // 1000 0000
RS = 0;
RW = 1;
EN = 0;
_nop_();
EN = 1;
_nop_();
_nop_();
tmp = databuffer;
EN = 0;
_nop_();
}
}
void Write_Cmd_Func(char cmd)
{
check_busy();
RS = 0;
RW = 0;
EN = 0;
_nop_();
databuffer = cmd;
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
void Write_Data_Func(char dataShow)
{
check_busy();
RS = 1;
RW = 0;
EN = 0;
_nop_();
databuffer = dataShow;
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
void Delay15ms() //@11.0592MHz
{
unsigned char i,
j;
i = 27;
j = 226;
do
{
while (--j)
;
} while (--i);
}
void Delay5ms() //@11.0592MHz
{
unsigned char i,
j;
i = 9;
j = 244;
do
{
while (--j)
;
} while (--i);
}
void LCD1602_INIT()
{
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
Write_Cmd_Func(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
//(5)写指令 38H:显示模式设置
Write_Cmd_Func(0x38);
//(6)写指令 08H:显示关闭
Write_Cmd_Func(0x08);
//(7)写指令 01H:显示清屏
Write_Cmd_Func(0x01);
//(8)写指令 06H:显示光标移动设置
Write_Cmd_Func(0x06);
//(9)写指令 0CH:显示开及光标设置}
Write_Cmd_Func(0x0c);
}
void LCD1602_showLine(char row,char col,char *string){ // row 选择显示行数 col 显示位置 string 显示的内容
switch (row)
{
case 1:
Write_Cmd_Func(0x80+col);
while (*string)
{
Write_Data_Func(*string);
string++;
/* code */
}

/* code */
break;
case 2:
Write_Cmd_Func(0x80+0x40+col);
while (*string)
{
Write_Data_Func(*string);
string++;
/* code */
}
break;
}
}
void main()
{
char position = 0x80 + 0x05;
char dataShow = 'L';
LCD1602_INIT();
// Write_Cmd_Func(position);
// //选择要显示的地址
// Write_Data_Func(dataShow);
// //发送要显示的字符
LCD1602_showLine(1,5,"NO.1"); //第一行的第五个位置开始显示 NO.1
LCD1602_showLine(2,0,"xiaoliutongxue"); // 第二行的第零个位置开始显示 小刘同学
}