本文最后更新于35 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
LCD1602简介
LCD1602字符型液晶(每行显示16个字符,一共可以显示两行)——一种专门用来显示字母、数字、符号的点阵型液晶模块。它由若干个5×7或者5×10的点阵字符组成,每个点阵字符位都可以用来显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,所以它不能很好的显示图片。
LCD1602主要技术参数
LCD1602的接口
VSS:接地 VDD:接电源正级,注意电压即可 VL: 接地 RS: 当RS为高电平时,对1602进行数据字节的传输操作,而为低电平时,则进行命令字节的传输操作 R/W:高电平时读取1602的数据,反之则对1602进行写数据操作 E :使能信号,可以看作LCD1602的时钟信号,用以产生脉冲实现写数据操作等等 D0~D7:数据并行口,用于传输数据,占用8个IO口
基本操作时序
LCD1602一般只作为显示使用,不太需要进行读操作和读数据
写指令
输入:RS=L,RW=L,D0~D7=指令码,E=高脉冲(将E置为高电平后,再给低电平以产生高脉冲)
写数据
输入:RS=H,RW=L,D0~D7=数据,E=高脉冲
RAM地址映射图
LCD1602内带有80×8位(80字节)的RAM缓冲区,但只有每一列的前16个字符才会显示在屏幕上,如果写入了前16给以外的地址,则显示不出来,当屏幕整体移动一定位时,可以显示原本不显示的数据,两边地址的数据也会移动
指令说明
初始化步骤一般为
- 显示模式设置
- 显示开/关光标设置
- 数据控制
- 数据指针设置(即选择要存放数据的地址)
- 读或写数据
Proteus仿真原理图
程序
#include <reg52.h>
sbit E = P2^6;
sbit RS = P2^4;
sbit RW = P2^5;
sbit S1 = P3^0;
sbit S2 = P3^1;
sbit S3 = P3^2;
sbit S4 = P3^3;
#define LCD_Data P0
unsigned long second = 0;
unsigned char Hour = 0;
unsigned char Min = 0;
unsigned char Sec = 0;
unsigned char flag1 = 1;
unsigned int time0 = 0;
unsigned int time1 = 0;
unsigned char S1_flag0 = 1;
unsigned char S1_flag1 = 1;
unsigned char S2_flag0 = 1;
unsigned char S2_flag1 = 1;
unsigned char S3_flag0 = 1;
unsigned char S3_flag1 = 1;
unsigned char S4_flag0 = 1;
unsigned char S4_flag1 = 1;
void LCD_Delay(unsigned char time)
{
while(time--)
{
unsigned char i = 0;
for(i = 0; i<123;i++);
}
}
void LCD_WriteCom(unsigned char com)
{
RS = 0;
RW = 0;
LCD_Data = com;
E = 1;
LCD_Delay(1);
E = 0;
LCD_Delay(1);
}
void LCD_WriteData(unsigned char Data)
{
RS = 1;
RW = 0;
LCD_Data = Data;
E = 1;
LCD_Delay(1);
E = 0;
LCD_Delay(1);
}
void LCD_Init(void)
{
LCD_WriteCom(0x38); //设置16x2显示,5x7点阵,8位数据接口
LCD_WriteCom(0x0C); // 0000 1100
LCD_WriteCom(0x06); //0000 0110
LCD_WriteCom(0x01); //清除 复位
}
void LCD_SetCursor(unsigned Line, unsigned char Column)
{
if(Line == 1)
{
LCD_WriteCom(0x80|(Column - 1));
}
else
{
LCD_WriteCom(0x80|(Column) + 0x40);
}
}
void LCD_ShowChar(unsigned char Line, unsigned char Column,unsigned char Char)
{
LCD_SetCursor(Line, Column);
LCD_WriteData(Char);
}
void LCD_ShowNum(unsigned char Line, unsigned char Column, unsigned char Num)
{
LCD_SetCursor(Line, Column);
LCD_WriteData('0' + Num);
}
void Clock_Set(unsigned char hour,unsigned char min,unsigned char sec)
{
second =(hour*3600) + (min*60) +(sec);
}
void Clock_Config(void)
{
Hour =(second / 3600 / 10 * 10 + second / 3600 % 10);
Min = (second % 3600 / 60 / 10 * 10 + second % 3600 / 60 % 10);
Sec = (second % 3600 % 60 / 10 * 10 + second % 3600 % 60 % 10);
}
void Time_Clock(void)
{
LCD_ShowNum(1,1,Hour / 10);
LCD_ShowNum(1,2,Hour % 10); //时
LCD_ShowNum(1,4,Min / 10);
LCD_ShowNum(1,5,Min % 10); //分
LCD_ShowNum(1,7,Sec / 10);
LCD_ShowNum(1,8,Sec % 10); //秒
if(flag1 == 1)
{
LCD_ShowChar(1,3,':');
LCD_ShowChar(1,6,':');
}
else if(flag1 == 0)
{
LCD_ShowChar(1,3,' ');
LCD_ShowChar(1,6,' ');
}
if(Hour > 23)
{
Hour = 0;
}
if(Min > 59)
{
Min = 0;
}
if(Sec > 59)
{
Sec = 0;
}
}
void Time_Init(void)
{
EA = 1;
TMOD = 0x01;
ET0 = 1;
TR0 = 1;
TH0 = 64535 / 256;
TL0 = 64535 % 256;
}
void main(void)
{
LCD_Init();
Time_Init();
Clock_Set(12,34,03); //设置时间
Clock_Config();
while(1)
{
Time_Clock();
}
}
void Time_IT(void) interrupt 1
{
time0 ++;
time1 ++;
TH0 = 64535/256;
TL0 = 64535%256;
if(time0 == 500)
{
if(flag1 == 0)
{
flag1 = 1;
}
else if(flag1 == 1)
{
flag1 = 0;
}
time0 =0;
}
if(time1 == 20) //非阻塞按键扫描
{
S1_flag1 = S1_flag0; //保存上一次的值
S1_flag0 = S1; //获取新的值
S2_flag1 = S2_flag0; //保存上一次的值
S2_flag0 = S2; //获取新的值
S3_flag1 = S3_flag0; //保存上一次的值
S3_flag0 = S3; //获取新的值
S4_flag1 = S4_flag0; //保存上一次的值
S4_flag0 = S4; //获取新的值
if(S1_flag1 == 1 && S1_flag0 == 0)
{
Hour++;
}
if(S2_flag1 == 1 && S2_flag0 == 0)
{
Hour--;
}
if(S3_flag1 == 1 && S3_flag0 == 0)
{
Min++;
}
if(S4_flag1 == 1 && S4_flag0 == 0)
{
Min--;
}
time1 = 0;
}
}