一、基础知识
LCD1602 表示最多每行16个字符,共两行
1、引脚介绍
2、基本操作时序
读状态:输入:RS=L,RW=H,E=H; 输出:D0~D7=状态字
写指令:输入:RS=L,RW=L,D0~D7=指令码,E=高脉冲 输出:无
读数据:输入:RS=H,RW=H,E=H; 输出:D0~D7=数据
写数据:输入:RS=H,RW=L,D0~D7=数据,E=高脉冲
3、状态字说明
STA0~6 表示当前数据地址指针的数值
控制器每次进行读写操作之前,需要进行读写检测,一定要确保STA7为0(STA7为0时表示 液晶空闲,否则为1表示液晶正忙数据无效)
4、显示区间
DDRAM
注:字符1的表示:1+0X30('0')
5、指令码设置与功能
指令码:80H+地址码(0~27H,40H~67H) 功能:设置数据地址指针
指令码:02H 功能: 显示回车(数据指针清零)
写指令:38H 功能: 显示模式设置
写指令:08H 功能: 显示关闭
写指令:06H 功能: 显示光标移动设置
写指令:0CH 功能:显示开及光标设置
指令码:01H 功能: 显示清屏(数据指针清零、所有显示清零) 【清除液晶显示屏上的数据】
设置光标移动方向以及显示屏移动方向
DB1为1表示写入新数据以后,光标后移;为0表示写入新数据以后,光标向前移动;
DB0为1表示写入新数据以后,显示屏向右移动;为1表示写入新数据以后,显示屏不移动;
DB4:用于设置数据总线数,当DL=0 时表示有四位管脚(数据总线为4),当DL=1时表示有八位管脚 【如果为八位数据,可以先传高四位再传低四位】
DB3: 用于设置显示屏的行数,为0时表示显示1行,为1时表示显示两行
DB2: 用于设置点阵数,为0时表示5*7的点阵,为1时表示5*10的点阵
DB1、DB0均为随机设置数,一般设置为0
二、LCD1602的使用
1、初始化
2、写命令(RS=L),设置显示坐标
3、写数据 (RS=H)
R/W 我们一般是写数据,所以此处设置为0
设置使能使其完成一个上升沿到下降沿的信号,此时DB0~DB7就完成了写入
根据该表格设置时钟信号
三、LCD1602函数相关代码
#include <reg52.h>
//引脚定义
sbit LCD1602_RS=P2^6;
sbit LCD1602_RW=P2^5;
sbit LCD1602_E=P2^7;
#define LCD1602_DATAPORT P0
typedef unsigned char u8;
//延时函数
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
//LCD1602写命令函数
void lcd1602_write_cmd(u8 cmd)
{
LCD1602_RS=0; //RS设置为0表示写命令
LCD1602_RW=0;
LCD1602_E=0;
LCD1602_DATAPORT=cmd;
delay_ms(1);
LCD1602_E=1;
delay_ms(1);
LCD1602_E=0;
}
//LCD1602写数据函数
void lcd1602_write_data(u8 dat)
{
LCD1602_RS=1; //RS设置为1表示写数据
LCD1602_RW=0;
LCD1602_E=0;
LCD1602_DATAPORT=dat;
delay_ms(1);
LCD1602_E=1;
delay_ms(1);
LCD1602_E=0;
}
//LCD1602初始化函数,将各指令写入
void lcd1602_init(void)
{
//以下指令的初始化没有先后顺序
lcd1602_write_cmd(0x38); //功能设置指令
lcd1602_write_cmd(0x0c); //显示开关控制指令(不使用光标)
lcd1602_write_cmd(0x06); //模块设置指令(光标向右移动,显示屏不移动)
lcd1602_write_cmd(0x01); //清屏指令
}
//清屏函数
void lcd1602_clear(void){
lcd1602_write_cmd(0x01); //调用清屏指令,可以实现清屏的对外显式调用
}
//显示字符串函数 x:0~15 y:0~1
void lcd1602_show_string(u8 x,u8 y,u8 *str) //x,y用于表示显示屏起始显示的位置(x为列,y为行) str为字符串首地址,*str用于取其指针指向的数据
{
u8 i=0;
if(y>1||x>15) return;
if(y<1)
{ //从第一行开始显示
while(*str != '\0' )
{
if(i<16-x){ //第一行只能最多显示16-x个数,超过了就在第二行显示
lcd1602_write_cmd(0x80+x+i); //为了在不同位置上显示,地址要不断改变(通过i) 【0x80+x为起始显示位置】
} else {
lcd1602_write_cmd(0x80+0x40+x+i-16); //由于i从前面已经加到了16,用其减16可得出第二行开始从0列显示并不断往后加
}
lcd1602_write_data(*str); //将字符串显示出来
str++;
i++;
}
} else { //从第二行开始
while(*str!='\0'){
if(i<16-x){ //第一行只能最多显示16-x个数,超过了就在第二行显示
lcd1602_write_cmd(0x80+0x40+x+i); //【0x80+x+0x40为起始显示位置(第二行)】
} else {
lcd1602_write_cmd(0x80+x+i-16); //第二行不够显示则到第一行显示
}
lcd1602_write_data(*str); //将字符串显示出来
str++;
i++;
}
}
}
//单个数据的显示
void lcd1602_show_data(u8 x,u8 y,u8 dat){
if(y>1||x>15) return;
if(y<1) //第一行
{
lcd1602_write_cmd(0x80+x); //显示位置的设定
} else { //第二行开始显示
lcd1602_write_cmd(0x80+0x40+x);
}
lcd1602_write_data(dat+0x30); //转换为ascell码才能显示,于是加上0x30
}
void main()
{
lcd1602_init(); //lcd1602初始化
lcd1602_show_string(0,0,"hello world"); //数据会一直显示,所以不用放在while中
lcd1602_show_string(0,1,"正确");
while(1){
//动态显示则需放在此处
}
}