简介
LCD ( Liquid Crystal Display 的简称)液晶显示器。能够同时显示16×2,32个字符,是一种专门用来显示字母、数字、符号等的点阵型液晶模块。
LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。该显示屏的优点是耗电量低、体积小、辐射低。
LCD1602主要用来显示数字、字母、图形以及少量自定义字符。可以显示2行16个字符,拥有16个引脚,其中8位数据总线D0-D7,和RS、R/W、EN三个控制端口,工作电压为5V,并且带有字符对比度调节V0和背光源AK。
我们所用的LCD屏的命名,基本都是按照其分辨率来进行命名的 比如 lcd1602 就是分辨率为 16×2 lcd12864 就是分辨率为 128×64
- 引脚1(VSS/GND):地引脚
- 引脚2(VDD/VCC):电源引脚
- 引脚3(VL):液晶显示器对比度引脚,接正电源时对比度最弱,接地时对比度最高,使用时可以通过外接一个电位器调整其对比度
- 引脚4(RS):寄存器选择脚,高电平时选择数据寄存器、低电平时选择指令寄存器
- 引脚5(R/W):读(read)/写(write)信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或显示地址;当RS为低电平,R/W为高电平时,可以读忙信号;当RS为高电平,R/W为低电平时,可以写入数据
- 引脚6(E):使能端,当E端由高电平跳变为低电平时,液晶模块执行命令
- 引脚7-14(D0~D7):8位双向数据线 用于单片机向1602写入数据和从1602读取数据
- 引脚15:背光源正极
- 引脚16:背光源负极
LCD1602共16个管脚,但分类很好分类,其中一个VCC和GND用于给1602供电,一个VCC和GND用于给背光源供电,剩下三个功能引脚:RS(数据命令选择端),R/W(读写选择端),E(使能信号),还有8个D0~D7分别为8位双向数据线传输数据。RS为寄存器选择,高电平选择数据寄存器,低电平选择指令寄存器。R/W为读写选择,高电平进行读操作,低电平进行写操作。E端为使能端,后面和时序联系在一起。
LCD1602液晶模块的读/写操作、显示屏和光标的操作都是通过指令编程来实现的(其中,1为高电平,0为低电平),分别介绍如下
- 指令1:清屏。指令码01H,光标复位到地址00H
- 指令2:光标复位。光标复位到地址00H
- 指令3:输入方式设置。其中,I/D表示光标的移动方向,高电平右移,低电平左移;S表示显示屏上所有文字是否左移或右移,高电平表示有效,低电平表示无效
- 指令4:显示开关控制。其中,D用于控制整体显示的开与关,高电平表示开显示,低电平表示关显示;C用于控制光标的开与关,高电平表示有光标,低电平表示无光标;B用于控制光标是否闪烁,高电平闪烁,低电平不闪烁
- 指令5:光标或字符移位控制。其中,S/C表示在高电平时移动显示的文字,低电平时移动光标
- 指令6:功能设置命令。其中,DL表示在高电平时为8位总线,低电平时为4位总线;N表示在低电平时为单行显示,高电平时双行显示;F表示在低电平时显示5×7的点阵字符,高电平时显示5×10的点阵字符
- 指令7:字符发生器RAM地址设置
- 指令8:DDRAM地址设置
- 指令9:读忙信号和光标地址。其中,BF为忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平则表示不忙
- 指令10:写数据
- 指令11:读数据
LCD初始化的过程,也就是对LCD进行写指令的过程,具体的指令如下:
写指令38H:1602显示,5X7点阵,8位数据总线 (指令6)
写指令0CH:开启显示屏,关光标,光标不闪烁 (指令4)
写指令0x06:显示地址地址加1,即写一个数据后,显示位置右移一位 (指令3)
写指令01H:显示清屏
软件流程图(显示字符串为例)
程序分析
lcd1602.c
/**********************************
作者:特纳斯电子
网站:https://www.mcude.com
联系方式:46580829(QQ)
淘宝店铺:特纳斯电子
**********************************/
/**********************************
包含头文件
**********************************/
#include "lcd1602.h"
/**********************************
函数定义
**********************************/
/****
*******1602检测忙函数
*****/
void lcd1602_check_busy()
{
P0=0xff;
do
{
LCD1602_RS=0;
LCD1602_RW=1;
LCD1602_E=0;
LCD1602_E=1;
} while(LCD1602_BUSY==1);
LCD1602_E=0;
}
/****
*******1602写数据忙函数
*****/
void lcd1602_write_date(uchar date)
{
lcd1602_check_busy();
LCD1602_E=0;
LCD1602_PORT=date;
LCD1602_RS=1;
LCD1602_RW=0;
LCD1602_E=1;
LCD1602_E=0;
}
/****
*******1602写命令函数
*****/
void lcd1602_write_com(uchar com)
{
lcd1602_check_busy();
LCD1602_E=0;
LCD1602_PORT=com;
LCD1602_RS=0;
LCD1602_RW=0;
LCD1602_E=1;
LCD1602_E=0;
}
/****
*******LCD1602显示字符函数
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* dat:所要显示的字符,输入格式 ' '
*****/
void lcd1602_display_char(uchar hang, uchar add, uchar dat)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
lcd1602_write_date(dat);
}
/****
*******LCD1602显示字符串函数
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* dat:所要显示的字符串,输入格式 " "
*****/
void lcd1602_display_str(uchar hang, uchar add, uchar *dat)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
while(*dat != '\0')
{
lcd1602_write_date(*dat++);
}
}
/****
*******LCD1602显示时间函数(显示格式:**:**:**)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* time:所要显示的时间,以秒为单位
*****/
void lcd1602_display_time(uchar hang, uchar add, uint time)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
lcd1602_write_date(time/3600/10%10+48); //时钟的十位
lcd1602_write_date(time/3600/1%10+48); //时钟的个位
lcd1602_write_date(':'); //;
lcd1602_write_date(time%3600/60/10%10+48); //分钟的十位
lcd1602_write_date(time%3600/60/1%10+48); //分钟的个位
lcd1602_write_date(':'); //;
lcd1602_write_date(time%60/10%10+48); //秒钟的十位
lcd1602_write_date(time%60/1%10+48); //秒钟的个位
}
/****
*******LCD1602显示温度函数(显示格式:**.*℃)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* temp:所要显示的温度
*****/
void lcd1602_display_temp(uchar hang, uchar add,uint temp)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
lcd1602_write_date(temp/100%10+48);
lcd1602_write_date(temp/10%10+48);
lcd1602_write_date('.');
lcd1602_write_date(temp/1%10+48);
lcd1602_write_date(0xdf); //显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码
lcd1602_write_date(0x43); //显示"C"符号,0x43是液晶屏字符库里大写C的地址码
}
/****
*******LCD1602显示湿度函数(显示格式:**.*%)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* humi:所要显示的湿度
*****/
void lcd1602_display_humi(uchar hang, uchar add,uint humi)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
lcd1602_write_date(humi/100%10+48);
lcd1602_write_date(humi/10%10+48);
lcd1602_write_date('.');
lcd1602_write_date(humi/1%10+48);
lcd1602_write_date('%');
}
/****
*******LCD1602显示光照强度函数(显示格式:**.*lx)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* light:所要显示的光照强度
*****/
void lcd1602_display_light(uchar hang, uchar add,uint light)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
lcd1602_write_date(light/100%10+48);
lcd1602_write_date(light/10%10+48);
lcd1602_write_date('.');
lcd1602_write_date(light/1%10+48);
lcd1602_write_date('L');
lcd1602_write_date('x');
}
/****
*******LCD1602显示距离函数(显示格式:***cm)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* distance:所要显示的距离
*****/
void lcd1602_display_distance(uchar hang, uchar add,uint distance)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(distance > 99)
lcd1602_write_date(distance/100%10+48);
if(distance > 9)
lcd1602_write_date(distance/10%10+48);
lcd1602_write_date(distance/1%10+48);
lcd1602_write_date('c');
lcd1602_write_date('m');
lcd1602_write_date(' ');
lcd1602_write_date(' ');
}
/****
*******LCD1602显示气体浓度(显示格式:000ppm)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* gas_value:所要显示的气体浓度
*****/
void lcd1602_display_gas(uchar hang, uchar add,uint gas_value)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(gas_value > 999)
lcd1602_write_date(gas_value/1000%10+48);
if(gas_value > 99)
lcd1602_write_date(gas_value/100%10+48);
if(gas_value > 9)
lcd1602_write_date(gas_value/10%10+48);
lcd1602_write_date(gas_value/1%10+48);
lcd1602_write_date('p');
lcd1602_write_date('p');
lcd1602_write_date('m');
lcd1602_write_date(' ');
lcd1602_write_date(' ');
lcd1602_write_date(' ');
}
/****
*******LCD1602显示PM2.5(显示格式:000ug/m3)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* pm25_value:所要显示的PM2.5
*****/
void lcd1602_display_pm25(uchar hang, uchar add,uint pm25_value)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(pm25_value > 999)
lcd1602_write_date(pm25_value/1000%10+48);
if(pm25_value > 99)
lcd1602_write_date(pm25_value/100%10+48);
if(pm25_value >= 9)
lcd1602_write_date(pm25_value/10%10+48);
lcd1602_write_date(pm25_value/1%10+48);
lcd1602_write_date('u');
lcd1602_write_date('g');
lcd1602_write_date('/');
lcd1602_write_date('m');
lcd1602_write_date('3');
lcd1602_write_date(' ');
}
/****
*******1602显示数字(2位)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* num:所要显示的数据,2位
*****/
void lcd1602_display_num_2(uchar hang, uchar add, uint num)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
lcd1602_write_date(num/10%10+48); //十
lcd1602_write_date(num/1%10+48); //个
}
/****
*******LCD1602显示数字函数(最大4位)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* num:所要显示的数据,最大4位
*****/
void lcd1602_display_num(uchar hang, uchar add, uint num)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(num > 999)
lcd1602_write_date(num/1000%10+48); //千
if(num > 99)
lcd1602_write_date(num/100%10+48); //百
if(num > 9)
lcd1602_write_date(num/10%10+48); //十
lcd1602_write_date(num/1%10+48); //个
lcd1602_write_date(' ');
lcd1602_write_date(' ');
lcd1602_write_date(' ');
}
/****
*******LCD1602显示时间函数
*******格式:第一行:年-月-日
*************第二行:时:分:秒 星期(英文缩写)
*******参量定义:time_buf[8]:时间数组
*****/
void lcd_display_alltime(uchar time_buf[8])
{
uint nian;
uchar yue,ri,shi,fen,miao,xingqi;
nian = time_buf[0]/0x10*1000 + time_buf[0]%0x10*100 + time_buf[1]/0x10*10 + time_buf[1]%0x10;
yue = time_buf[2]/0x10*10 + time_buf[2]%0x10;
ri = time_buf[3]/0x10*10 + time_buf[3]%0x10;
shi = time_buf[4]/0x10*10 + time_buf[4]%0x10;
fen = time_buf[5]/0x10*10 + time_buf[5]%0x10;
miao = time_buf[6]/0x10*10 + time_buf[6]%0x10;
xingqi = time_buf[7]/0x10*10 + time_buf[7]%0x10;
lcd1602_display_num(1,0,nian); //显示年
lcd1602_write_com(0x84);
lcd1602_write_date('-'); //显示 -
lcd1602_display_num_2(1,5,yue); //显示月
lcd1602_write_date('-'); //显示 -
lcd1602_display_num_2(1,8,ri); //显示日
lcd1602_display_num_2(2,2,shi); //显示时
lcd1602_write_date(':'); //显示 :
lcd1602_display_num_2(2,5,fen); //显示分
lcd1602_write_date(':'); //显示 :
lcd1602_display_num_2(2,8,miao); //显示秒
if(xingqi == 1)
{
lcd1602_display_str(2,11,"Mon "); //显示星期一英文缩写
}
else if(xingqi == 2)
{
lcd1602_display_str(2,11,"Tues"); //显示星期二英文缩写
}
else if(xingqi == 3)
{
lcd1602_display_str(2,11,"Wed "); //显示星期三英文缩写
}
else if(xingqi == 4)
{
lcd1602_display_str(2,11,"Thur"); //显示星期四英文缩写
}
else if(xingqi == 5)
{
lcd1602_display_str(2,11,"Fri "); //显示星期五英文缩写
}
else if(xingqi == 6)
{
lcd1602_display_str(2,11,"Sat "); //显示星期六英文缩写
}
else
{
lcd1602_display_str(2,11,"Sun "); //显示星期天英文缩写
}
}
/****
*******LCD1602清屏函数
*****/
void lcd1602_clean()
{
lcd1602_write_com(0x01);
}
/****
*******LCD1602初始化函数
*****/
void Lcd1602_Init()
{
lcd1602_write_com(0x38);
lcd1602_write_com(0x0c);
lcd1602_write_com(0x06);
lcd1602_write_com(0x01);
}
lcd1602.h
/**********************************
作者:特纳斯电子
网站:https://www.mcude.com
联系方式:46580829(QQ)
淘宝店铺:特纳斯电子
**********************************/
#ifndef _LCD1602_H_
#define _LCD1602_H_
/**********************************
包含头文件
**********************************/
#include "main.h"
/**********************************
PIN口定义
**********************************/
#define LCD1602_PORT P0 //数据总线P0.0-P0.7
sbit LCD1602_RS=P2^5; //数据/命令选择引脚P2.5
sbit LCD1602_RW=P2^6; //读/写选择P2.6
sbit LCD1602_E=P2^7; //使能信号引脚P2.7
sbit LCD1602_BUSY=P0^7; //检测状态引脚P0.7
/**********************************
函数声明
**********************************/
void lcd1602_display_char(uchar hang, uchar add, uchar dat); //LCD1602显示字符函数
void lcd1602_display_str(uchar hang, uchar add, uchar *dat); //LCD1602显示字符串函数
void lcd1602_display_time(uchar hang, uchar add, uint time); //LCD1602显示时间函数(显示格式:**:**:**)
void lcd_display_alltime(uchar time_buf[8]); //LCD1602显示时间函数(显示年月日时分秒星期)
void lcd1602_display_temp(uchar hang, uchar add,uint temp); //LCD1602显示温度函数(显示格式:**.*℃)
void lcd1602_display_humi(uchar hang, uchar add,uint humi); //LCD1602显示湿度函数(显示格式:**.*%)
void lcd1602_display_light(uchar hang, uchar add,uint light); //LCD1602显示光照强度函数(显示格式:**.*Lx)
void lcd1602_display_distance(uchar hang, uchar add,uint distance); //LCD1602显示距离函数(显示格式:***cm)
void lcd1602_display_gas(uchar hang, uchar add,uint gas_value); //LCD1602显示气体浓度(显示格式:000ppm)
void lcd1602_display_pm25(uchar hang, uchar add,uint pm25_value); //LCD1602显示PM2.5(显示格式:000ug/m3)
void lcd1602_display_num(uchar hang, uchar add,uint num); //LCD1602显示数字函数(最大4位)
void lcd1602_clean(); //LCD1602清屏函数
void Lcd1602_Init(); //LCD1602初始化函数
void lcd1602_display_num_2(uchar hang, uchar add, uint num);
#endif