C51单片机学习笔记(六)——液晶显示屏的使用
文章目录
1.LCD1602的认识
- 液晶显示屏简称液晶、LCD。各种型号的液晶通常是按显示字符的行数或液晶点阵的行、列进行命名的。1602的意思就是每一行显示16个字符,共可以显示2行,常见的液晶还有0801、0802、1601等,这类液晶是字符型液晶,只能显示ASCII码字符。而LCD12864属于图形型液晶,由128*64个像素点构成,可以显示各种图形包括汉字。
- LCD1602可显示2行ASCII码字符,每行包括16个5*10点阵(像素),有16个引脚,其实物图如下所示:
2.LCD1602的引脚及其功能
3.LCD模块的内部结构
- LCD1602模块的内部结构分为三部分:LCD控制器、LCD驱动器、LCD显示器
- LCD控制器和LCD驱动器一般由专用集成电路实现,大部分是HD44780或兼容芯片,HD44780是低功耗CMOS大规模点阵LCD控制器,它包含有下面的电路,他们的功能如下表:
- LCD1602显示字符的过程
HD447780内部有80*8bit的DDRAM缓冲区,其显示位置与DDRAM地址的对应关系如下表:
- 一行有40个地址,可以存入40个字符数据,但每行最多只能显示其中的16个。可以用多余的地址存入其他数据,实现显示的快速切换。注意:编程时需要将表中的地址加上80H才能正确显示,如果要在第一行显示“R”,应该将“R”的ASCII码(0x52)写到地址0x80+ox03即0x83处。
4.LCD1602的工作时序
- LCD1602的读操作时序
LCD1602读操作编程流程:
- 给RS加电平(1为数据,0为指令)给R/W加高电平(读模式)
- E = 1(使能,高电平有效),延时
- LCD1602送数据到DB0~DB7
- E = 0
- 读结束
- LCD1602的写操作时序
LCD1602的写操作编程流程:
- 给RS加电平(1为数据,0为指令),R/W = 0(为写)
- 单片机送数据到DB0~DB7
- E = 1 (拉高使能线)
- E = 0,写入生效
- 改变RS、R/W的状态,为下次操作做准备
5.LCD1602的指令说明
LCD1602液晶模块共有11条指令,下面根据上面的表格做出说明:
- 指令一:清除显示,指令码为0x01,其实质是将DDRAM全部写入空格的ASCII码0x20,地址计数器AC清零。该过程需要时间较长。
- 指令二:光标复位,光标返回00H(复位到屏的左上方),地址计数器AC清零,DDRAM内容不变
- 指令三:光标和显示模式设置。N——设置光标的移动方向,N=1时,读或写一个字符后,地址加1,光标加1;N=0时,地址减1,光标减1.S——用于设置整屏字符是否左移或右移,当S= 1且N = 1时,写一个字符整平左移,当S= 1且N = 0时,写一个字符时整屏显示右移,若S = 0,则整屏字符移动无效,因此常用的光标右移指令为0x06
- 指令4:显示开/关控制D——控制整体显示的开与关,高电平显示,低电平关显示;C——控制光标的开关,高电平表示有光标,低电平无光标;B——控制光标是否杉树,高电平闪烁,低电平不闪烁常用的开显示关光标的指令为0x0c
- 指令5:命令光标或字符移动。S/C控制光标或字符,R/L控制左右
(S/C)(R/L) = (0)(0),文字不动,光标左移一格,AC减1
(S/C)(R/L) = (0)(1),文字不动,光标右移一格,AC加1
(S/C)(R/L) = (1)(0),文字全部右移一格,光标不动
(S/C)(R/L) = (1)(1),文字全部左移一格,光标不动- 指令六:功能设置命令DL——高电平为8位数据总线,低电平为4位数据总线;N——低电平单行显示,高电平双行显示;F——低电平显示57的点阵字符,高电平显示510的点阵字符,常用的两行、八位数据总线、5*7的点阵指令为0x38
- 指令七:指令为0x40+add(当D5-D0全为0时,D7~D0为0x40)该指令用于设置自定义字符的CGRAM地址。ADD前三位用于选择字符,后三位用于选择字符的8位字模数据
- 指令八:指令为0x80+add,用于设置下一个要存入数据的DDRAM地址。add的范围是0x00~0x27,对应第一行,0x40-0x67对应显示第二行,每行可输入40个字符,默认只能显示前16个,可以通过指令3的字符移动指令来显示其他内容
- 指令九:读忙信号和光标地址。BF:忙标志位,高电平表示忙,此时模块不能就收命令或数据,如果为低电平表示闲,可以操作
- 指令10:写数据
- 指令11:读数据
6.LCD1602的编程实例
- 这是我的液晶电路原理图,主要看一下与哪个引脚相连。
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
/*******引脚定义*******/
sbit RS = P1^0;
sbit RW = P1^1;
sbit E = P1^2;
#define data1602 P0
sbit BF = data1602^7; //BF表示data1602的最高位,判断是忙还是闲
/*******延时函数*******/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*******忙检测函数*******/
bit LCD_busy()
{
bit busy;
P0 = 0xff;//防止干扰
RS = 0; //命令模式
RW = 1; //读模式
E = 1;
busy = BF;//将忙标志位的数值赋给busy
E = 0;
return busy;
}
/*******写命令函数*******/
void LCD_write_cmd(uchar cmd)//cmd为需要写的命令
{
while(LCD_busy());//只有当LCD_busy()为0(闲)时才跳出循环
RS = 0; //命令模式
RW = 0; //写模式
data1602 = cmd; //将命令内容的十六进制送到P0端口
E = 1;
E = 0; //使能端,高电平有效,使命令送到LCD1602的DB0~DB7
}
/*******写数据函数*******/
void LCD_write_data(uchar dat)//dat为需要写的数据
{
while(LCD_busy());//只有当LCD_busy()为0(闲)时才跳出循环
RS = 1; //数据模式
RW = 0; //写模式
data1602 = dat; //将数据内容的十六进制送到P0端口
E = 1;
E = 0; //使能端,高电平有效,使命令送到LCD1602的DB0~DB7
}
/*******LCD初始化函数*******/
void LCD_init()
{
LCD_write_cmd(0x38); //将设置“两行、八位数据、5*7的点阵”命令写入LCD的控制器
LCD_write_cmd(0x0c); //开显示关光标
LCD_write_cmd(0x06); //光标右移指令
LCD_write_cmd(0x01); //清除显示
}
/*******LCD写显示地址函数*******/
void LCD_write_address(uchar x,uchar y)
{
x&=0x0f; //列地址限制在0~15之间
y&=0x01; //行地址限制在0~1
if(y==0)
LCD_write_cmd(x|0x80);//数据指针=80+地址变量,写入列地址
else
LCD_write_cmd((x+0x40)|0x80); //如果是第二行,将列地址写入
}
/*******LCD显示函数*******/
void LCD_display(uchar x,uchar y,uchar buf) //x:列 y:行,buf:显示的字符
{
LCD_write_address(x,y);//先将地址写入
LCD_write_data(buf); //再写入要显示的数据
}
/*******main函数*******/
void main()
{
LCD_init();
LCD_display(2,0,'H');
LCD_display(3,0,'e');
LCD_display(4,0,'l');
LCD_display(5,0,'l');
LCD_display(6,0,'o');
LCD_display(8,0,'W');
LCD_display(9,0,'o');
LCD_display(10,0,'r');
LCD_display(11,0,'l');
LCD_display(12,0,'d');
LCD_display(8,1,'W');
LCD_display(9,1,'D');
while(1);
}
效果如下: