很久没玩过51单片机了(.. )…,整理一下玩LCD1602模块的一些笔记。
LCD1602液晶显示模块可显示2行、16字/行
的字符,绝大部分的LCD1602液晶显示模块都是基于HD77480及其兼容芯片来设计的。
单片机: STC89C52
开发板: HC6800-MS
LCD1602引脚
VSS
:电源地
VDD
:电源正极
V0
:液晶显示偏压信号,连接电位器,用于调节液晶显示的对比度
RS
:数据/命令选择端,当RS=1
时,从D0
到D7
读/写数据;当RS=0
时,从D0
到D7
读状态或写指令
RW
:读/写选择端,当RW=1
时,进行读操作;当RW=0
时,进行写操作
E
:使能端。进行读操作时,要使E
处于高电平;进行写操作时,要使E
处于下降沿
D0
~D7
:并行输入/输出端
A
:背光源的正极
K
:背光源的负极
基本操作时序
读操作时序
写操作时序
寄存器
LCD1602模块有两个8位寄存器,分别为指令寄存器和数据寄存器,可以通过RS
和R/W
输入信号的组合来选择指定的寄存器进行相应的操作。
读状态:
- 输入:
RS=0
、RW=1
、E=1
- 输出:
<D0~D7>=<状态字>
写指令:
- 输入:
RS=0
、RW=0
、<D0~D7>=<指令码>
、E=<高脉冲>
- 输出:无
读数据:
- 输入:
RS=1
、RW=1
、E=1
- 输出:
<D0~D7>=<数据>
写数据:
- 输入:
RS=1
、RW=0
、<D0~D7>=<数据>
、E=<高脉冲>
- 输出:无
状态字说明
D7
:读写操作使能,当D7=1
时,禁止读写;当D7=0
时,允许读写
D6~0
:当前数据地址指针的数值
因为LCD1602搭载的芯片运算速度较慢,当模块正在进行内部操作时,不接受任何外部指令和数据,此时,忙标志位BF
为高电平。所以每次进行读写操作前,都必须进行读忙,将状态标志位BF
读到D7
,确保D7=0
。
LCD1602指令
51单片机可以直接访问LCD1602的指令寄存器和数据寄存器,在LCD1602进行内部操作前,来自51单片机的控制信息和数据将分别暂存于此,这些控制信息和数据的组合即为LCD1602的指令。
清显示
归位
设置输入模式
显示开/关控制
游标或显示移位元
功能设置
CGRAM地址设置
DDRAM地址设置
读忙标志BF和AC
写数据到CGRAM或DDRAM
从CGRAM或DDRAM中读数据
CGROM、DDRAM和CGRAM
在LCD1602模块内,与字符显示相关的存储器有CGROM、DDRAM、CGRAM。对于显示一些常用字符,其字模数据已存储于CGROM中,再调用时,只需使用语法P=<常用字符>;
即可调用;但如果需要显示CGROM中不存在的字符,则必须先在CGRAM中自定义,再写入DDRAM。
CGROM
CGROM内存储了192个常用字符的字模数据,只能读出,不能写入。这些字模数据恰好与其对应的字符的ASCII值相等,因此,单片机会根据某常用字符的ASCII值从CGROM中读出与之值相等的字符数据,并将该字符数据写入DDRAM,即可显示对应的常用字符。另外,在CGROM中,地址0x00
~ 0x07
内容为空,由用户在CGRAM中进行自定义,再调用自定义的字符。
DDRAM
DDRAM用于存储从CGROM或CGRAM读出的需要LCD1602显示的字符的字模数据,容量为80字节,地址范围:
其中用于存储需要显示的字符的字模数据的两段为:
其余部分用于存储字符显示相关的设置,例如字符的移动。
CGRAM
CGRAM用于存储自定义的字符的字模数据,可自定义8个点阵列大小为5×7
的字符或4个点阵列大小为5×11
的字符。以5×7
模式为例,一个字模数据大小为8字节,需要8个地址来表示,每8个地址组成一个地址段,存储一个字模数据;第一个地址段的起始为0x40
,该地址段对应CGROM中的地址0x00
;第二个地址段的起始为0x48
,该地址段对应CGROM中的地址0x01
;第三个地址段的起始为0x50
,该地址段对应CGROM中的地址0x02
,依此类推。
举个栗子
#include<reg51.h> #include<intrins.h> sbit RS=P2^6; sbit RW=P2^5; sbit E=P2^7;
char Text0[]="Hello,"; char Text1[]="world!";
int ReadBusy() { int temp; RS=0; RW=1; _nop_(); P0=0xff; _nop_(); E=1; _nop_(); temp=P0; _nop_(); E=0; return(temp&0x80); }
void Delay5ms() { unsigned char i,j; i=59; j=90; do { while(--j); } while(--i); }
void Write_Com(char com) { while(ReadBusy()); RS=0; RW=0; _nop_(); P0=com; _nop_(); E=1; Delay5ms(); E=0; Delay5ms(); }
void Write_Dat(char dat) { while(ReadBusy()); RS=1; RW=0; _nop_(); P0=dat; _nop_(); E=1; Delay5ms(); E=0; Delay5ms(); }
void init() { Delay5ms(); Delay5ms(); Delay5ms(); Write_Com(0x38); Delay5ms(); Write_Com(0x38); Delay5ms(); Write_Com(0x38); Write_Com(0x0c); }
void main() { int i,j; init(); Write_Com(0x80); for(i=0;i<6;i++) { Write_Dat(Text0[i]); } Write_Com(0x80+0x40); for(j=0;j<6;j++) { Write_Dat(Text1[j]); } }
|
#include<reg51.h> #include<intrins.h> sbit RS=P2^6; sbit RW=P2^5; sbit E=P2^7;
char Image0[]={0x08,0x1F,0x12,0x0F,0x0A,0x1F,0x02,0x00}; char Image1[]={0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00}; char Image2[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00};
int ReadBusy() { int temp; RS=0; RW=1; _nop_(); P0=0xff; _nop_(); E=1; _nop_(); temp=P0; _nop_(); E=0; return(temp&0x80); }
void Delay5ms() { unsigned char i,j; i=59; j=90; do { while(--j); } while(--i); }
void Write_Com(char com) { while(ReadBusy()); RS=0; RW=0; _nop_(); P0=com; _nop_(); E=1; Delay5ms(); E=0; Delay5ms(); }
void Write_Dat(char dat) { while(ReadBusy()); RS=1; RW=0; _nop_(); P0=dat; _nop_(); E=1; Delay5ms(); E=0; Delay5ms(); }
void init() { Delay5ms(); Delay5ms(); Delay5ms(); Write_Com(0x38); Delay5ms(); Write_Com(0x38); Delay5ms(); Write_Com(0x38); Write_Com(0x0c); }
void main() { int x,y,z; init(); Write_Com(0x40); for(x=0;x<sizeof(Image0);x++) { Write_Dat(Image0[x]); } Write_Com(0x48); for(y=0;y<sizeof(Image1);y++) { Write_Dat(Image1[y]); } Write_Com(0x50); for(z=0;z<sizeof(Image2);z++) { Write_Dat(Image2[z]); } Write_Com(0x80+0x00); Write_Dat(0x00); Write_Com(0x80+0x02); Write_Dat(0x01); Write_Com(0x80+0x04); Write_Dat(0x02); }
|
本文内容如有错误,请在评论区多多指教,非常感谢φ(≧ω≦*)♪。
参考资料
51单片机LCD1602程序详解
超详细讲解,LCD1602电路与驱动
基于51单片机点亮LCD1602+自定义字符
单片机 1602 CGRAM、CGROM及DDRAM的作用