历史上的今天
今天是:2026年03月24日(星期二)
2023年03月24日 | 51单片机 | 实现SMC1602液晶屏显示实例
2023-03-24 来源:zhihu
LCD1602
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1602的意思是每行显示16个字符,一共可以显示两行。如果是12232液晶(图形型液晶)则表示由122列32行组成,即共有122*32个点
p.s.注意使用温度,通常液晶的工作范围为0~+55℃,存储温度范围为-22~+60℃。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
引脚情况:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
基本操作时序:
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
| 状态 | 输入 | 输出 |
| 读状态 | RS=0R/W=1E=1 | D0~D7=状态字 |
| 读数据 | RS=1R/W=1E=1 | D0~D7=数据 |
| 写指令 | RS=0R/W=0E=1D0~D7=指令码E=1 | 无 |
| 写数据 | RS=1R/W=0E=1D0~D7=数据E=1 | 无 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RAM内部映射:80个字节

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
状态字说明://状态字反应了当前液晶屏的情况,当STA7为1时说明显示器正在忙碌状态,不可进行操作
STA0~STA6表示当前地址指针的数值
STA7表示读/写使能,=1表示进制,=0表示允许

p.s.原则上每次对控制器读写操作之前都必须进行读写检测,确保STA7=0,实际操作中由于单片机操作速度慢于液晶控制的反应速度,可以不进行读写检测而只进行简短的延时。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
数据指针设置:
用户可以通过以下的数据地址指针访问内部的80个字节RAM,用来设置数据地址
80H+地址码(0~27H,40~67H)
例:对第一个地址进行操作,0x80+0x01
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
其他指令码:
| 01H | 显示清屏(数据指针清零,所有显示清零) |
| 02H | 显示回车(数据指针清零) |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
初始化:
显示模式设置:38H

显示开/关及光标设置

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
读写操作时序:
读操作

写操作

操作时间参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
操作方式:
对LCD的操作可以分为数据和指令两部分。
通过操作RS,R/W,E,执行四种操作:读状态,读数据,写指令,写数据
D0~D7用来输入输出指令码和数据
————————————————————————————————————————————
LCD1602使用实例:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
设计要求:
使用LCD1602显示两行字符,显示两行字,两个按键控制着显示或清屏

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
设计思路:
初始化液晶显示屏 //参照上文"初始化"
打开使能
指令码操作
设置16*2显示,5*7点阵,8位数据结构
开显示,显示光标,不闪烁
读写完字符后地址指针+1,光标+1,整屏显示不移动
清屏
设置地址显示的首字符
初始化中断
打开中断
外部中断0和1
死循环等待中断
按键中断
按键"显示"
循环写入数据(字符数组)
指令"换行"
循环写入第二行数据
按键"清屏"
指令"清屏"
子函数 //参照上文"读写操作时序表"
写数据
写指令
1 #include
2 typedef unsigned char uchar;
3 sbit en = P3 ^ 4;
4 sbit rs = P3 ^ 5;
5 uchar code table1[] =
6 {
7 "SMC1602 0x01..."
8 };
9 uchar code table2[] =
10 {
11 " Hugh Dong."
12 };
13 void Delay(uchar m)
14 {
15 uchar i, j;
16 for (i = m; i > 0; --i)
17 for (j = 110; j > 0; --j);
18 }
19 /* 写数据 */
20 void write_date(uchar date)
21 {
22 //参考写操作时序图
23 rs = 1; //RS高电平,写数据
24 P2 = date; //写入数据,对应时序图t_SP2数据建立
25 Delay(5);
26 en = 1; //打开使能,给E一个高脉冲,开始写入数据
27 Delay(5);
28 en = 0; //关闭使能,写入数据完成
29 }
30 /* 写指令 */
31 void write_com(uchar com)
32 {
33 //基本原理同写数据
34 rs = 0; //RS低电平,写指令
35 P2 = com;
36 Delay(5);
37 en = 1;
38 Delay(5);
39 en = 0;
40 }
41 /* 初始化LCD */
42 void Init()
43 {
44 en = 1;
45 write_com(0x38); //00111000 设置16*2显示,5*7点阵,8位数据接口
46 write_com(0x0E); //00001110 开显示,显示光标,不闪烁
47 write_com(0x06); //00000110 读写字符后地址指针+1,光标+1,屏幕不移动
48 write_com(0x01); //清屏
49 write_com(0x80 + 0x01); //设置数据地址指针从第一个开始
50 }
51 int main()
52 {
53 /* 初始化LCD */
54 Init();
55 Delay(100);
56 /* 初始化中断 */
57 EA = 1;
58 EX0 = 1;
59 EX1 = 1;
60 /* 死循环 */
61 while(1);
62 }
63 void Display()interrupt 0 using 1
64 {
65 uchar i;
66 for (i = 0; i < 16; ++i) //遍历逐个写入第一行数据
67 {
68 write_date(table1[i]);
69 Delay(20);
70 }
71 write_com(0x02); //换行
72 write_com(0x80 + 0x40); //数据地址指针指向第二行
73 for(i = 0; i < 16; ++i) //逐个遍历写入第二行数据
74 {
75 write_date(table2[i]);
76 Delay(20);
77 }
78 }
79 void Clear() interrupt 1 using 1
80 {
81 write_com(0x01);
82 }
史海拾趣
|
单片机的内部、外部结构(一) 一、单片机的外部结构 拿到一块芯片,想要使用它,首先必须要知道怎样连线,我们用的一块称之为89C51的芯片,下面我们就看一下如何给它连线。 1、 电源:这当然是必不可少的了。单片机使用的是5V电源,其中正极接40引 ...… 查看全部问答> |
|
请教AddDevice函数是做什么用的呀?为什么文件系统过滤驱动AddDevice函数? 向高手请教 请教AddDevice函数是做什么用的呀?为什么文件系统过滤驱动AddDevice函数?… 查看全部问答> |
|
我用的是三星arm2440,ce5.0,我发现一个奇怪的问题,机器重启后,第一次调用SetLocalTime设置时间不对,设置的时间是一个默认值2008-1,但是以后再调用SetLocalTime就不会出现这个问题了,请问这是什么原因,是ce的一个bug,SetLocalTime对应的应 ...… 查看全部问答> |
|
在option.h中 mclk=320000000这个值是根据什么确定的呢? 如果对它进行修改,会发生什么影响? 另外,在uart传输数据的时候,收发双方如何保证自己这边的频率与对方差不多? 当我们在ulcon中设定了某种祯格式,对方如何知道?如何检错? 我 ...… 查看全部问答> |
|
我电脑两个串口上连接两个GPRS MODEM同时拨号上网,默认情况下是使用一个连接.我想在程序中控制两个连接怎么同时使用呀,即有的数据通过一个连接发送出去,另外一些数据通过另外一个连接发送出去呀,应该怎么办呀,请各位帮忙.非常感谢呀!… 查看全部问答> |
|
由于缺乏高端SoC芯片技术,国内IC设计企业在嵌入式CPU开发上一直处于落后状态。可喜的是,随着全球半导体产业的技术转移及自身的努力,近年来国内已涌现出一些嵌入式CPU开发优势企业。下面就由福州卓跃教育具 ...… 查看全部问答> |
|
我在使用CYSteam例程来测速速度的时候一直出现了一个问题,下载固件程序后,在设备管理器中能够看到该驱动已经正常安装了,但是在console或者是官方提供的CYSteam中无法识别。一直以为是驱动的程序的问题。但是我利用购买的开发板就没有这个问题。 ...… 查看全部问答> |




