LCD1602原理与应用
LCD1602原理
写程序要遵循硬件电路->硬件接口->软件编程三部分。
LCD1602可以显示2行16个字符,用用16个引脚,主要控制端口为RS,R/W,EN。
通过RS,R/W可以选择不同的读写操作:
RS | R/W | 操作 |
---|---|---|
0 | 0 | 写命令 |
0 | 1 | 读取BUSY Flag及AC地址 |
1 | 0 | 写数据 |
1 | 1 | 读数据 |
结合EN,可分为下面三种操作:
读Flag:RS=0,RW=1,EN高电平
写命令:RS=0,RW=0,EN高脉冲
写数据:RS=1,RW=0,EN高脉冲
LCD1602的时序图
写操作:
根据RS的不同,写操作分为写指令和写数据两种:
- 写指令:
- RS置为0
- R/W置为0
- EN置为0
- 输入CMD
- 延时
- EN置为1
- 延时
- EN置为0
- 写数据:
- RS置为1
- R/W置为0
- EN置为0
- 输入DAT
- 延时
- EN置为1
- 延时
- EN置为0
读操作一般不常见,因此在本文中就不提及了。
LCD1602的常用指令
数据指针:指令码为0x80+地址码,地址码范围为0x00-0x27,0x40-0x67。
整屏左移:0x18
整屏右移:0x1c
根据常用指令,需要先将LCD1602初始化:
- 写指令0x38:表示为8位数据,两行显示,5*7点阵
- 延时
- 写入0x38,显示模式设置
- 写指令0x0f:显示开关控制
- 写指令0x06:输入方式
LCD1602在单片机上的原理图
LCD实验
Q:初始化和写数据/指令完成之后,进行测试,第一位出现空白,即字符从第二位开始
A:数据指针需要初始化。在初始化中加入写指令0x80(数据地址为0x80)
PS:同时为了防止一开始LCD就显示多余的数据,在写数据地址指令前,加入清屏指令,即写指令0x01.
Q:写入数据之后,该字符不停的闪烁。
A:忘记加 while(1);
该语句的功能是保持LCD的设置不变。
1. LCD显示一行字符
初始化完成之后,只需要按顺序输出字符就可:
for(i =0;i<11;i++){
Write_Data(table[i]);
Delay(1);
}
2. LCD显示两行字符
跟实验1基本步骤一致,但是需要显示第二行前,把位置指针指向0x80+0x40,即第二行的位置
3. LCD移位
需要先将LCD显示的字符放置到显示屏的后端,然后再通过左移指令进行整体左移:
Write_Cmd(0x80+0x13);
for(i =0;i<11;i++){
Write_Data(table[i]);
Delay(1);
}
Write_Cmd(0xc0+0x13);
for(i =0;i<10;i++){
Write_Data(second[i]);
Delay(1);
}
for(i = 0;i<16;i++){
Write_Cmd(0x18);
Delay(500);
}
while(1);
4. 完成动态LCD,实现动态秒表
思路:用定时器来确定时长,然后记录秒数,再通过LCD动态显示
#include <REGX52.H>
#include "Delay.h"
#define uchar unsigned char
#define uint16 unsigned int
sbit RW = P2^5;
sbit RS = P2^6;
sbit EN = P2^7;
uchar cnt=0;
uchar num,min,sec1,sec2;
void display(uchar min,sec1,sec2);
void Write_Cmd(uchar command){
RS = 0;
RW = 0;
Delay(1);
P0 = command;
Delay(1);
EN = 1;
Delay(5);
EN =0;
}
void Write_Data(uchar dat){
RS = 1;
RW = 0;
Delay(1);
P0 = dat;
Delay(1);
EN = 1;
Delay(5);
EN =0;
}
void Timer0Init(){
TMOD =0x01;
TL0 = 0XCD;
TH0 = 0XD4;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void Init(){
EN = 0;
Delay(1);
Write_Cmd(0x38);
Write_Cmd(0x0e);
Write_Cmd(0x06);
Write_Cmd(0x01);
Write_Cmd(0x80);
Delay(1);
}
void main(){
Timer0Init();
Init();
while(1){
display(min,sec1,sec2);
}
while(1);
}
void Timer0() interrupt 1{
TL0 = 0XCD;
TH0 = 0XD4;
cnt++;
if(cnt==100){
cnt = 0;
num++;
if(num==120) num =0;
min = num/60;
sec1 = (num%60)%10;
sec2 = (num%60)/10;
}
}
void display(uchar min,sec1,sec2){
Write_Cmd(0x80);
Write_Data(0x30+min);
Write_Data(':');
Write_Data(0x30+sec2);
Write_Data(0x30+sec1);
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)