在之前的文章中讲到了显示器件–数码管,但是数码管两个缺点比较严重:
1、显示单一、体积大,显示复杂内容时就相形见绌了。
2、动态显示时序要求高,对于单片机但线程MCU来说很容易出现显示闪烁等问题。
LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路及其扩展驱动电路,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。不同厂家生产的LCD1602芯片可能有所不同,但使用方法都是一样的。
点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共16×8=128个点组成。显示屏上64×16个显示单元与显示RAM区的1024字节相对应,每一字节的内容与显示屏上相应位置的亮暗对应。
字符型液晶显示模块是一种专门用于显示字母、数字和符号等的点阵式LCD,常用16×2,20×2和40×2等的模块。
引脚定义如下:
编号 | 符号 | 引脚说明 | 编号 | 符号 | 引脚说明 |
---|---|---|---|---|---|
1 | VSS | 电源地 | 9 | D2 | 数据 |
2 | VDD | 电源正极 | 10 | D3 | 数据 |
3 | VL | 液晶显示偏压 | 11 | D4 | 数据 |
4 | RS | 数据/命令选择 | 12 | D5 | 数据 |
5 | R/W | 读/写选择 | 13 | D6 | 数据 |
6 | E | 使能信号 | 14 | D7 | 数据 |
7 | D0 | 数据 | 15 | BLA | 背光源正极 |
8 | D1 | 数据 | 16 | BLK | 背光源负极 |
引脚1:VSS为地电源。
引脚2:VDD接5V正电源。
引脚3:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”现象,使用时可以通过一个10kQ的电位器调整其对比度。
引脚4:RS为寄存器选择脚,高电平时选择数据寄存器、低电平时选择指令寄存器。
引脚5:R/W为读/写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或显示地址;当RS为低电平,R/W为高电平时,可以读忙信号;当RS为高电平,R/W为低电平时,可以写入数据。
引脚6:E端为使能端,当E端由高电平跳变为低电平时,液晶模块执行命令。
引脚7-14:D0~D7为8位双向数据线。
引脚15:背光源正极。
引脚16:背光源负极。
指令集 – 重要
序号 | 指令 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 清屏 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2 | 光标复位 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | x |
3 | 输入方式设置 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S |
4 | 显示开关控制 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B |
5 | 光标或字符移位控制 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | x | x |
6 | 功能设置 | 0 | 0 | 0 | 0 | 1 | DL | N | F | x | x |
7 | 字符发生存储器地址设置 | 0 | 0 | 0 | 1 | - | - | 字符发生存储器地址 | - | - | - |
8 | 数据存储器地址设置 | 0 | 0 | 1 | - | - | - | 显示数据存储器地址 | - | - | - |
9 | 读忙标志或地址 | 0 | 1 | BF | - | - | - | 计数器地址 | - | - | - |
10 | 写入数据至CGRAM或DDRAM | 1 | 0 | - | - | - | - | 要写入的数据内容 | - | - | - |
11 | 从CGRAM或DDRAM中读取数据 | 1 | 1 | - | - | - | - | 读取的数据内容 | - | - | - |
(1)指令1:清屏。指令码01H,光标复位到地址00H。
(2)指令2:光标复位。光标复位到地址00H。
(3)指令3:输入方式设置。其中,I/D表示光标的移动方向,高电平右移,低电平左移;S表示显示屏上所有文字是否左移或右移,高电平表示有效,低电平表示无效。
(4)指令4:显示开关控制。其中,D用于控制整体显示的开与关,高电平表示开显示,低电平表示关显示;C用于控制光标的开与关,高电平表示有光标,低电平表示无光标;B用于控制光标是否闪烁,高电平闪烁,低电平不闪烁。
(5)指令5:光标或字符移位控制。其中,S/C表示在高电平时移动显示的文字,低电平时移动光标。
(6)指令6:功能设置命令。其中,DL表示在高电平时为8位总线,低电平时为4位总线;N表示在低电平时为单行显示,高电平时双行显示;F表示在低电平时显示5×7的点阵字符,高电平时显示5×10的点阵字符。
(7)指令7:字符发生器RAM地址设置。
(8)指令8:DDRAM地址设置。
(9)指令9:读忙信号和光标地址。其中,BF为忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平则表示不忙。
(10)指令10:写数据。
(11)指令11:读数据。
连接方式
LCD1602与单片机的连接有两种方式,一种是直接控制方式,另一种是所谓的间接控制方式。它们的区别只是所用的数据线的数量不同,其他都一样。
1.直接控制方式
LCD1602的8根数据线和3根控制线E,RS和R/W与单片机相连后即可正常工作。一般应用中只须往LCD1602中写入命令和数据,因此,可将LCD1602的R/W读/写选择控制端直接接地,这样可节省1根数据线。VO引脚是液晶对比度调试端,通常连接一个10kΩ的电位器即可实现对比度的调整;也可采用将一个适当大小的电阻从该引脚接地的方法进行调整,不过电阻的大小应通过调试决定。
2.间接控制方式
间接控制方式也称为四线制工作方式,是利用HD44780所具有的4位数据总线的功能,将电路接口简化的一种方式。为了减少接线数量,只采用引脚DB4~DB7与单片机进行通信,先传数据或命令的高4位,再传低4位。采用四线并口通信,可以减少对微控制器I/O的需求,当设计产品过程中单片机的I/O资源紧张时,可以考虑使用此方法。 可以看做是一个LCD1602加上一个IIC转并口输出模块。
基本操作
读状态。输入RS=0,RW=1,E=高脉冲。输出:D0—D7为状态字。
读数据。输入RS=1,RW=1,E=高脉冲。输出:D0—D7为数据。
写命令。输入RS=0,RW=0,E=高脉冲。输出:无。
写数据。输入RS=1,RW=0,E=高脉冲。输出:无。
字符库
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
因为1602识别的是ASCII码,试验可以用ASCII码直接赋值,在单片机编程中还可以用字符型常量或变量赋值,如’A’。
读的时候,先读上面那行,再读左边那列,如:感叹号!的ASCII为0x21,字母B的ASCII为0x42(前面加0x表示十六进制)。
驱动程序
1、公共代码
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sfr LCD_DATA = P0; //LCD数据端P0
sbit LCD_EN = P2^2; //定义下面通过LCD_EN来操作P2^7口,1602液晶使能控制端
sbit LCD_WR = P2^1; //定义下面通过lcdrw来操作P2^5口,1602读写选择端
sbit LCD_RS = P2^0; //定义选数据寄存器选指令寄存器控制端
void DelayTime1ms(unsigned int DelayValue); //1ms延时
void DelayTime10ms(unsigned int DelayValue); //10ms延时
uchar code table0[] = {"0123456789ABCDEF"}; //要写入1602液晶的数据
2、初始化
void init_1602()
{
LCD_WR = 0;
LCD_EN = 0;
write_com(0x38); //设置LCD为16*2显示、5*7点阵、8位数据接口模式
write_com(0x0c); //开显示、不显示光标
//write_com(0x08); // 关显示
//write_com(0x0e); // 开显示有光标但不闪烁
//write_com(0x0f); // 开显示有光标且闪烁
write_com(0x06); //写一个字符后,地址指针自加1
write_com(0x01); //显示清0
}
3、写指令
void write_com(uchar com)
{
LCD_WR = 0; //LCD_WR为读写控制端,LCD_WR=0,这里可不写
LCD_RS = 0; //液晶rs接口为0时,写指令,rs为1时写数据
LCD_DATA = com; //将要写的指令赋给P0口,由1602读写操作时序图,先将指令赋给P0口,延时后将使能端LCD_EN置高,再延时一段时间,然后将LCD_EN置低,这样指令就写入到LCD了
DelayTime1ms(5);
LCD_EN = 1;
DelayTime1ms(5);
LCD_EN = 0;
}
4、写一个数据
void write_data(uchar date)//与写指令类似,这里LCD_RS设为1
{
LCD_RS = 1; //液晶rs接口为1时,写数据,rs为1时写数据
LCD_DATA = date; //将要写的指令赋给P0口,由1602读写操作时序图,先将指令赋给P0口,延时后将使能端LCD_EN置高,再延时一段时间,然后将LCD_EN置低,这样指令就写入到LCD了
DelayTime1ms(5);
LCD_EN = 1;
DelayTime1ms(5);
LCD_EN = 0;
}
5、读一个数据
uchar Read_Lcd_Data()
{
unsigned char byte;
LCD_DATA = 0xff; //防止低电平干扰拉低数据位
Lcd_RW = 1;
Lcd_RS = 1;
DelayTime1ms(5); //写个延时程序 为什么加延时请看时序图
LCD_EN = 0;
byte = LCD_DATA ;
DelayTime1ms(5);
LCD_EN = 1;
return byte;
}
6、显示一位数字
void write_sfm(unsigned char hang,unsigned char wei,unsigned char shuzhi)//用于在1602显示数字内容
{
if(hang == 1){
write_com(wei+0x80); //定义显示在液晶的第一行位置
write_data(0x30+shuzhi); //由1602液晶字库可知,0~9的数据码分别对应0x30~0x39
} else if(hang == 2) {
write_com(wei+0xc0); //定义显示在液晶的第二行位置
write_data(0x30+shuzhi); //由1602液晶字库可知,0~9的数据码分别对应0x30~0x39
}
}