单片机学习 | 入门教程:LCD1602显示屏使用详解
一、初识LCD1602
- 定义:LCD1602(Liquid Crystal Display)是一种工业字符型液晶,能够同时显示 16×02 即 32 字符(16 列两行)。
- 引脚说明:如下图
第
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
脚
:背光源负极。
注意:
1602 液晶模块的读写操作,屏幕和光标的操作都是通过指令编程来实现的。(说明:1 为高电平、0 为低电平)
二、操作时序图
读操作时序图
写操作时序图
各时序参数
三、LCD如何显示字符
1、内部显示地址:
2、具体实现
要显示字符时,第一步先输入显示字符地址,也就是告诉模块在哪里显示字符,其次是输入数据。
例如:例如第二行第一个字符的地址是 40H,那么是否直接写入 40H 就可以将光标定位在第二行第 一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7 恒定为高电平 1 所以实际写入的数据应该是 01000000B(40H) +10000000B(80H)=11000000B(C0H)。
3、代码演示(观察时序图)
①写命令函数封装
//写命令
//RS 和 R/W 同为低电平时可以写入指令或者显示地址
void write_cmd(char cmd)
{
checkBusy();
RS = 0;
RW = 0;
EN = 0;
_nop_();
DataBuffer = cmd;//给DB0 - DB7的电平
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
②写数据函数封装
//写数据
//RS 为高电平 R/W为低电平时可以写入数据(读文档所得)
void write_Data(char dataShow)
{
checkBusy();
RS = 1;
RW = 0;
EN = 0;
_nop_();
DataBuffer = dataShow;
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
③读忙信号函数封装
//RS 为低电平 R/W为高电平时可以读忙信号
void checkBusy()
{
char tmp = 0x80;
DataBuffer = 0x80;
while(tmp & 0x80){
RS = 0;
RW = 1;
EN = 0;
_nop_();
EN = 1;
_nop_();
_nop_();
tmp = DataBuffer;
EN = 0;
_nop_();
}
}
注意:读忙信号和光标地址。BF:为忙标志位,高电平表示忙,此时模块不能接收命令或
者数据,如果为低电平表示不忙。
④LCD初始化函数
void LCD1602_Init()
{
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
write_cmd(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
checkBusy();
//(5)写指令 38H:显示模式设置
write_cmd(0x38);
//(6)写指令 08H:显示关闭
write_cmd(0x08);
//(7)写指令 01H:显示清屏
write_cmd(0x01);
//(8)写指令 06H:显示光标移动设置
write_cmd(0x06);
//(9)写指令 0CH:显示开及光标设置
write_cmd(0x0C);
}
四、实现效果及代码
#include "reg52.h"
#include <intrins.h>
sbit RS = P1^0;
sbit EN = P1^4;
sbit RW = P1^1;
#define DataBuffer P0//定位8位数据线,P0端口组
void checkBusy()
{
char tmp = 0x80;
DataBuffer = 0x80;
while(tmp & 0x80){
RS = 0;
RW = 1;
EN = 0;
_nop_();
EN = 1;
_nop_();
_nop_();
tmp = DataBuffer;
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 write_cmd(char cmd)
{
checkBusy();
RS = 0;
RW = 0;
EN = 0;
_nop_();
DataBuffer = cmd;//给DB0 - DB7的电平
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
void write_Data(char dataShow)
{
checkBusy();
RS = 1;
RW = 0;
EN = 0;
_nop_();
DataBuffer = dataShow;
_nop_();
EN = 1;
_nop_();
_nop_();
EN = 0;
_nop_();
}
void LCD1602_Init()
{
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
write_cmd(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
checkBusy();
//(5)写指令 38H:显示模式设置
write_cmd(0x38);
//(6)写指令 08H:显示关闭
write_cmd(0x08);
//(7)写指令 01H:显示清屏
write_cmd(0x01);
//(8)写指令 06H:显示光标移动设置
write_cmd(0x06);
//(9)写指令 0CH:显示开及光标设置
write_cmd(0x0C);
}
void main()
{
char position = 0x80 + 0x05;//确认位置
char dataSH = 'L';//显示内容
LCD1602_Init();
write_cmd(position);//选择要显示的地址
write_Data(dataSH);//显示要发送的字符
}
作者:RunLy:)