LCD1602 是一种工业字符型液晶显示屏,能够同时显示 16x2 即 32 个字符。
LCD的显示控制
- 通过向 LCD1602 发送指令和数据来控制其显示内容。指令包括清屏、设置光标位置、显示模式等;数据则是要显示的字符的 ASCII 码。
- LCD1602 内部有一个控制器,负责接收和解析指令和数据,并控制液晶的显示。
lcd1602实物图
LCD1602引脚说明表
第 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 脚:背光源负极。
LCD内部控制器指令:
指令 1:清显示,指令码 01H,光标复位到地址 00H 位置。
指令 2:光标复位,光标返回到地址 00H。
指令 3:光标和显示模式设置。I/D:光标移动方向,高电平右移,低电平左移。实际上就是 控制从左到右写入还是从右至左的写入顺序。S:屏幕上所有文字是否左移或者右 移。高电平表示有效,低电平则无效。S=1 当写一个字符,整屏显示左移(ID=1)或 者右移(I/D=0),以得到光标不移动而屏幕移动的效果。S=0 当写一个字符,整屏显 示不移动。
指令 4:显示开关控制。D:控制整体显示的开与关,高电平表示开显示,低电平表示关显 示. C:控制光标的开与关,高电平表示有光标,低电平表示无光标. B:控制光 标是否闪烁,高电平闪烁,低电平不闪烁。
指令 5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。R/L:文字或 者光标移动方向,R 表示右移,L 表示左移。
指令 6:功能设置命令 DL:高电平时为 8 位总线,低电平时为 4 位总线。N:低电平时为单行显示,高电平时双行显示。F:低电平时显示 5×8 的点阵字符,高电平时显示 5×10
的点阵字符。
指令 7:字符发生器 RAM 地址设置。
指令 8:DDRAM 地址设置。
指令 9:读忙信号和光标地址。BF:为忙标志位,高电平表示忙,此时模块不能接收命令或 者数据,如果为低电平表示不忙。
指令 10:写数据。
指令 11:读数据
LCD1602指令集结解释:
一、清显示指令(指令 1)
- 功能:清除液晶显示屏上的所有字符,将显示内容清空,并将光标复位到左上角的初始位置。
- 参数说明:RS(寄存器选择)为 0 表示选择指令寄存器;R/W(读写选择)为 0 表示写操作;D7 - D0 的值为 “00000001”,其中低七位全为 0,最后一位为 1 表示执行清显示操作。
二、光标返回指令(指令 2)
- 功能:将光标移动到显示屏的左上角,即初始位置。如果在执行该指令时显示屏上有字符显示,光标将回到左上角,而显示内容不会被清除。
- 参数说明:RS 和 R/W 均为 0;D7 - D0 的值为 “0000001*”,其中低七位的具体值可能因不同的实现而有所不同,但通常最后一位为 1 表示执行光标返回操作。
三、置输入模式指令(指令 3)
- 功能:设置液晶显示屏的输入模式,包括光标移动方向和字符显示方向。
- 参数说明:RS 和 R/W 为 0;D7 - D0 的值为 “000001I/DS”,其中 “I/D” 位用于设置光标移动方向,当 “I/D” 为 1 时,光标向右移动,当 “I/D” 为 0 时,光标向左移动;“S” 位用于设置字符显示方向,当 “S” 为 1 时,整个显示内容向右移动,当 “S” 为 0 时,整个显示内容向左移动。
四、显示开 / 关控制指令(指令 4)
- 功能:控制液晶显示屏的显示状态,包括显示开关、光标显示和闪烁显示。
- 参数说明:RS 和 R/W 为 0;D7 - D0 的值为 “00001DCB”,其中 “D” 位用于控制显示开关,当 “D” 为 1 时,显示屏开启,当 “D” 为 0 时,显示屏关闭;“C” 位用于控制光标显示,当 “C” 为 1 时,光标显示,当 “C” 为 0 时,光标不显示;“B” 位用于控制闪烁显示,当 “B” 为 1 时,字符闪烁显示,当 “B” 为 0 时,字符不闪烁显示。
五、光标或字符移位指令(指令 5)
- 功能:将光标或整个显示内容向左或向右移动。
- 参数说明:RS 和 R/W 为 0;D7 - D0 的值为 “0001S/CR/L**”,其中 “S/C” 位用于选择是光标移位还是显示内容移位,当 “S/C” 为 1 时,显示内容移位,当 “S/C” 为 0 时,光标移位;“R/L” 位用于选择移位方向,当 “R/L” 为 1 时,向右移位,当 “R/L” 为 0 时,向左移位。
六、置功能指令(指令 6)
- 功能:设置液晶显示屏的工作模式,包括数据位数、显示行数和字符字体等。
- 参数说明:RS 和 R/W 为 0;D7 - D0 的值为 “001DLNF**”,其中 “DL” 位用于设置数据位数,当 “DL” 为 1 时,使用 8 位数据总线,当 “DL” 为 0 时,使用 4 位数据总线;“N” 位用于设置显示行数,当 “N” 为 1 时,显示两行,当 “N” 为 0 时,显示一行;“F” 位用于设置字符字体,当 “F” 为 1 时,使用 5x10 的字符字体,当 “F” 为 0 时,使用 5x8 的字符字体。
七、置字符发生存贮器地址指令(指令 7)
- 功能:设置自定义字符的存储地址,以便在液晶显示屏上显示自定义字符。
- 参数说明:RS 和 R/W 为 0;D7 - D0 的高三位为 “010”,低五位为自定义字符发生存贮器地址。
八、置数据存贮器地址指令(指令 8)
- 功能:设置要显示数据的存储地址,即确定在液晶显示屏上的哪个位置显示字符。
- 参数说明:RS 和 R/W 为 0;D7 - D0 的高三位为 “1”,低五位为显示数据存贮器地址。
九、读忙标志或地址指令(指令 9)
- 功能:读取液晶显示屏的忙标志(BF)和地址计数器的值,以确定液晶显示屏是否处于忙碌状态,以及当前的地址位置。
- 参数说明:RS 为 0,R/W 为 1;D7 - D0 的高七位为忙标志(BF)和地址计数器的值,低七位的具体含义取决于忙标志的值。当 BF 为 1 时,表示液晶显示屏处于忙碌状态,不能接受新的指令;当 BF 为 0 时,表示液晶显示屏可以接受新的指令。
十、写数到 CGRAM 或 DDRAM 指令(指令 10)
- 功能:将数据写入字符发生存贮器(CGRAM)或数据存贮器(DDRAM),以便在液晶显示屏上显示字符。
- 参数说明:RS 为 1,R/W 为 0;D7 - D0 的值为要写入的数据内容。
十一、从 CGRAM 或 DDRAM 读数指令(指令 11)
- 功能:从字符发生存贮器(CGRAM)或数据存贮器(DDRAM)读取数据,以便获取当前显示的字符内容。
- 参数说明:RS 为 1,R/W 为 1;D7 - D0 的值为从 CGRAM 或 DDRAM 读取的数据内容。
一、E 信号周期(tc)
- 含义:E 信号(使能信号)的周期时间。E 信号用于控制数据的传输和指令的执行。
- 极限值:最小值无特定要求,典型值为无具体数值,最大值为 400ns。这个参数决定了 E 信号的变化频率。
- 测试条件:针对引脚 E 进行测试。
二、E 脉冲宽度(tpw)
- 含义:E 信号高电平的持续时间。在这个时间段内,数据和指令被传输到 LCD1602。
- 极限值:最小值为 150ns。这个参数确保了数据传输的有效性。
- 测试条件:同样针对引脚 E 进行测试。
三、E 上升沿 / 下降沿时间(tR.tF)
- 含义:E 信号从低电平变为高电平的上升时间和从高电平变为低电平的下降时间。
- 极限值:最大值为 25ns。较快的上升沿和下降沿时间可以提高数据传输的速度和稳定性。
- 测试条件:针对引脚 E 进行测试。
四、地址建立时间(tSP1)
- 含义:在 E 信号有效之前,地址信号(RS 和 R/W 引脚以及数据总线 D0-D7 的一部分用于选择地址)需要稳定的时间。
- 极限值:最小值为 30ns。这个参数确保了地址信号在数据传输之前被正确设置。
- 测试条件:针对引脚 E、RS、R/W 进行测试。
五、地址保持时间(tHD1)
- 含义:在 E 信号变为无效之后,地址信号需要保持稳定的时间。
- 极限值:最小值为 10ns。这个参数确保了地址信号在数据传输完成后不会立即改变。
- 测试条件:针对引脚 E、RS、R/W 进行测试。
六、数据建立时间(读操作,to)
- 含义:在进行读操作时,数据总线 D0-D7 上的数据需要在 E 信号有效之前稳定的时间。
- 极限值:最大值为 100ns。这个参数确保了在读取数据时,数据已经准备好。
- 测试条件:针对引脚 DBO-DB7 进行测试。
七、数据保持时间(读操作,tHD2)
- 含义:在进行读操作时,数据总线 D0-D7 上的数据需要在 E 信号变为无效之后保持稳定的时间。
- 极限值:最小值为 20ns。这个参数确保了在读取数据完成后,数据不会立即改变。
- 测试条件:针对引脚 DBO-DB7 进行测试。
八、数据建立时间(写操作,tsP2)
- 含义:在进行写操作时,数据总线 D0-D7 上的数据需要在 E 信号有效之前稳定的时间。
- 极限值:最小值为 40ns。这个参数确保了在写入数据时,数据已经准备好。
- 测试条件:针对引脚 DBO-DB7 进行测试。
九、数据保持时间(写操作,tHD2)
- 含义:在进行写操作时,数据总线 D0-D7 上的数据需要在 E 信号变为无效之后保持稳定的时间。
- 极限值:最小值为 10ns。这个参数确保了在写入数据完成后,数据不会立即改变。
- 测试条件:针对引脚 DBO-DB7 进行测试。
写时序
- 首先,RS(寄存器选择)引脚确定是向指令寄存器还是数据寄存器写入。如果是写指令,RS 为低电平;如果是写数据,RS 为高电平。
- R/W(读写选择)引脚置为低电平,表示进行写操作。
- 然后,在 E(使能)信号有效之前,也就是 E 从低电平变为高电平之前,数据总线上的有效数据(要写入的数据内容)需要提前一段时间准备好,这个时间就是数据建立时间 tSP2。
- 接着,E 信号变为高电平,持续一段时间 tpw(E 脉冲宽度)。在这个时间段内,数据被写入到 LCD1602 中。
- 当 E 信号从高电平变为低电平时,数据总线上的数据还需要再保持一段时间 tHD2,以确保数据被正确写入。
读时序
- RS 引脚同样根据要读取的是指令寄存器还是数据寄存器来设置高低电平。
- R/W 引脚置为高电平,表示进行读操作。
- 在 E 信号有效之前,地址信息(通过 RS 和 R/W 以及其他控制信号确定读取的地址)需要提前一段时间稳定下来,这个时间就是地址建立时间 tSP1。
- E 信号变为高电平,持续一段时间 tpw。在这个时间段内,LCD1602 将数据输出到数据总线上。
- 数据总线上的数据在 E 信号有效期间是有效的,从 E 信号变为高电平开始,到数据稳定可以读取需要一段时间,这就是数据建立时间 to。
- 当 E 信号从高电平变为低电平时,数据总线上的数据还需要再保持一段时间 tHD2,以确保数据被正确读取。
液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电 平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在 哪里显示字符。
LCD1602内部显示地址:
LCD1602显示一个字符
被调函数如下:
#include <REG52.H>
#include "LCD1602.h"
#include <INTRINS.H>//下面的延迟函数中的_nop_()会用到
// 定义连接到 LCD 的引脚
sbit LCD_RS = P1^0;//寄存器选择,高电平时为数据寄存器,低电平时为指令寄存器
sbit LCD_RW = P1^1;//读写信号,高电平时为读,低电平时为写
sbit LCD_E = P1^4;//使能端,由高电平变为低电平时,液晶模块执行命令
// 定义数据端口
#define LCD_DatePort P0
// 延时函数,用于在操作 LCD 时提供必要的时间延迟
void LCD_Delay() //@11.0592MHz
{
unsigned char i, j;
_nop_();
// 设置两层循环进行延时
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
// 写指令函数
void LCD_writecommand(unsigned char command)
{
// 设置为指令寄存器
LCD_RS = 0; //ÉèÖüĴæÆ÷ΪָÁî¼Ä´æÆ÷
// 设置为写模式
LCD_RW = 0; //ÉèÖÃΪдµÄģʽ
// 将指令数据输出到数据端口
LCD_DatePort = command; //дָÁî
// 注意:由于使能端 E 的信号周期最小为 400ns,所以添加一个延时函数确保正常运行
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
// 写数据函数
void LCD_writedata(unsigned char Data)
{
// 设置为数据寄存器
LCD_RS = 1; //ÉèÖÃΪÊý¾Ýģʽ¼Ä´æÆ÷
// 设置为写模式
LCD_RW = 0;
// 将数据输出到数据端口
LCD_DatePort = Data; //дָÁî
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
// LCD 显示屏初始化函数
void LCD_init()
{
// 配置 8 位数据接口
LCD_writecommand(0x38);//ÅäÖÃ8λÊý¾Ý½Ó¿Ú
// 显示开,光标关,闪烁关
LCD_writecommand(0x0c);//ÏÔʾ¿ª ¹â±ê¹Ø ÉÁ˸¿ª
// 光标右移,画面不动
LCD_writecommand(0x06);//¹â±ê+1 »Ãæ²»¶¯
// 清屏
LCD_writecommand(0x01);//ÇåÆÁ
}
// 在特定位置显示字符函数
void LCD_showchar(unsigned char line,unsigned char columu,unsigned char Char)
{
if(line==1)
{
// 设置第一行的地址
LCD_writecommand(0x80|(columu - 1));
}
else
{
// 设置第二行的地址
LCD_writecommand(0x80|(columu - 1)+0x40);
}
// 写入字符数据
LCD_writedata(Char);
}
主函数只需输入相对应的行数和列数以及相应的字符,即可在显示屏上面显示:
LCD显示字符串:
被调函数:
#include <REG52.H>
#include "LCD1602.h"
#include <INTRINS.H>//下面的延迟函数中的_nop_()用到
// 定义与 LCD1602 连接的引脚
sbit LCD_RS = P1^0;//寄存器选择,高电平时数据寄存器,低电平时命令寄存器
sbit LCD_RW = P1^1;//读写信号线,高电平时读,低电平时写
sbit LCD_E = P1^4;//使能端,由高电平变为低电平时,液晶模块执行命令
#define LCD_DatePort P0//定义数据端口
// 延迟函数,用于满足液晶模块的时序要求
void LCD_Delay() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
// 写指令函数
void LCD_writecommand(unsigned char command)
{
LCD_RS = 0; //设置为指令寄存器
LCD_RW = 0; //设置为写模式
LCD_DatePort = command; //将指令写入数据端口
//注意:由于使能端 E 的信号周期最小为 400ns,所以添加一个延迟函数以确保正常运行
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
// 写数据函数
void LCD_writedata(unsigned char Data)
{
LCD_RS = 1; //设置为数据寄存器
LCD_RW = 0;
LCD_DatePort = Data; //将数据写入数据端口
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
// LCD 初始化函数
void LCD_init()
{
LCD_writecommand(0x38);//配置 8 位数据接口
LCD_writecommand(0x0c);//开启显示,光标关闭,闪烁关闭
LCD_writecommand(0x06);//光标移动,画面不移动
LCD_writecommand(0x01);//清屏
}
// 设置光标位置函数
void LCD_setcursor(unsigned char line,unsigned char columu)
{
if(line == 1)
{
LCD_writecommand(0x80|(columu - 1));
//设置第一行地址
}
else
{
LCD_writecommand(0x80|(columu - 1)+0x40);
//设置第二行地址
}
}
// 显示单个字符函数
void LCD_showchar(unsigned char line,unsigned char columu,unsigned char Char)
{
LCD_setcursor(line, columu);
LCD_writedata(Char);
//写入字符数据
}
// 显示字符串函数
void LCD_showstring(unsigned char line,unsigned char columu,unsigned char *string)
{
unsigned char i;
//这里使用char比使用int型更加节约资源
(char为0-255,int为-2147483648 到 2147483647)
LCD_setcursor(line, columu);
for(i = 0; string[i]!= '\0'; i++)
{
LCD_writedata(string[i]);
//逐个写入字符串中的字符
}
}
主函数:
LCD显示数字:
被调函数:
#include <REG52.H>
#include "LCD1602.h"
#include <INTRINS.H>//下面的延迟函数中用到_nop_()
//定义与 LCD1602 连接的引脚
sbit LCD_RS = P1^0;//寄存器选择,高电平数据寄存器,低电平命令寄存器
sbit LCD_RW = P1^1;//读写信号线,高电平读,低电平写
sbit LCD_E = P1^4;//使能端,由高电平变为低电平时,液晶模块执行命令
#define LCD_DatePort P0//定义数据端口
//延迟函数,用于满足液晶模块的时序要求
void LCD_Delay() //@11.0592MHz
{
unsigned char i, j;
_nop_();//空操作,占用一个机器周期
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
//写指令函数
void LCD_writecommand(unsigned char command)
{
LCD_RS = 0;//设置为命令寄存器
LCD_RW = 0;//设置为写模式
LCD_DatePort = command;//将指令写入数据端口
//注意:由于使能端 E 的信号周期最小为 400ns,所以添加一个延迟函数以确保正常运行
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
//写数据函数
void LCD_writedata(unsigned char Data)
{
LCD_RS = 1;//设置为数据寄存器
LCD_RW = 0;
//将数据输出到数据端口
LCD_DatePort = Data; //写入数据
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
//LCD 显示屏初始化函数
void LCD_init()
{
LCD_writecommand(0x38);//配置 8 位数据接口
LCD_writecommand(0x0c);//显示开,光标关,闪烁开
LCD_writecommand(0x06);//光标移动一位,画面不移动
LCD_writecommand(0x01);//清屏
}
//设置光标位置函数
void LCD_setcursor(unsigned char line,unsigned char columu)
{
if(line == 1)//如果是第一行
{
LCD_writecommand(0x80|(columu - 1));
//设置第一行地址
}
else//如果是第二行
{
LCD_writecommand(0x80|(columu - 1)+0x40);
//设置第二行地址
}
}
//显示单个字符函数
void LCD_showchar(unsigned char line,unsigned char columu,unsigned char Char)
{
LCD_setcursor( line, columu);//设置光标位置
LCD_writedata(Char);//写入字符数据
}
//显示字符串函数
void LCD_showstring(unsigned char line,unsigned char columu,unsigned char *string)
{
unsigned char i;
LCD_setcursor( line, columu);//设置光标位置
for(i = 0;string[i]!= '\0';i++)//循环直到字符串结束
{
LCD_writedata(string[i]);//逐个写入字符串中的字符
}
}
//幂运算函数
int LCD_pow(int x,int y)
{
unsigned char i;
int result = 1;
// 循环 y 次,每次将 result 乘以 x
for(i = 0;i < y;i++)
{
result *= x;
}
return result;
}
/*
这个函数用于计算整数 x 的 y 次幂。它通过一个循环,每次将当前的结果 result 乘以 x,循环执行 y 次。
最终返回 x 的 y 次幂的结果。这个函数在显示数字函数中用于计算数字的每一位对应的权值。
*/
//显示数字函数
void LCD_shownum(unsigned char line,unsigned char columu,unsigned int number,unsigned int length)
{
unsigned char i;
LCD_setcursor( line, columu);
// 从高位到低位逐个显示数字
for(i = length;i > 0;i--)
{
// 计算并显示每一位数字
LCD_writedata('0' + number/LCD_pow(10,i - 1)%10);
}
}
/*
这个函数用于在 LCD1602 上的特定行和列位置显示一个整数 number。
参数说明:
- line:表示要显示数字的行,通常为 1 或 2。
- columu:表示要显示数字的列位置。
- number:要显示的整数。
- length:数字的位数。
函数首先调用 LCD_setcursor 函数设置显示数字的起始位置。然后通过一个循环,从高位到低位逐个计算数字的每一位,并将其转换为字符后显示在 LCD1602 上。
具体计算每一位数字的方法是:先使用 LCD_pow 函数计算对应位的权值,然后用 number 除以该权值得到当前位的数字,再加上字符 '0' 的 ASCII 值转换为对应的数字字符进行显示。
*/
主函数:
#include <REG52.h>
#include <INTRINS.H>
#include "LCD1602.h"
//#include "timer.h"
//sbit LED = P1^1;
//sbit SHARK = P1^0;
void Delay500ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 22;
j = 3;
k = 227;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
LCD_init();
LCD_showchar(1,1,'L');
LCD_showstring(1,4,"hello,world");
LCD_shownum(2,5,66,2);
while(1)
{
}
}
成功显示!!