视频讲解:
视频讲解
一,LCD1602介绍:
LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。不同厂家生产的LCD1602芯片可能有所不同,但使用方法都是一样的。为了降低成本,绝大多数制造商都直接将裸片做到板子上。
二,连接方式:
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引脚定义:
LCD1602采用标准的14脚(无背光)或16脚(带背光)接口。 LCD引脚功能引脚如下:
1 VSS 电源地
2 VDD 电源正极
3 VL 液晶显示偏压
4 RS 数据/命令选择
5 R/W 读/写选择
6 E 使能信号
7 D0 数据
8 D1 数据
9 D2 数据
10 D3 数据
11 D4 数据
14 D7 数据
12 D5 数据
13 D6 数据
15 BLA 背光源正极
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端由高电平跳变为低电平时,液晶模块执行命令。
·引脚714:D0D7为8位双向数据线。
·引脚15:背光源正极。
·引脚16:背光源负极。
四,LCD1602指令介绍:
LCD1602液晶模块的读/写操作、显示屏和光标的操作都是通过指令编程来实现的(其中,1为高电平,0为低电平),分别如下:
(1)指令1:清屏。指令码01H,光标复位到地址00H。
(2)指令2:光标复位。光标复位到地址00H。
(3)指令3:输入方式设置。其中,I/D表示光标的移动方向,高电平右移,低电平左移;S表示显示屏上所有文字是否左移或右移,高电平表示有效,低电平表示无效。
(4)指令4:显示开关控制。其中,D用于控制整体显示的开与关,高电平表示开显示,低电平表示关显示;C用于控制光标的开与关,高电平表示有光标,低电平表示无光标;B用于控制光标是否闪烁,高电平闪烁,低电平不闪烁。
(5)指令5:光标或字符移位控制。其中,S/C表示在高电平时移动显示的文字,低电平时移动光标。
(6)指令6:功能设置命令。其中,DL表示在高电平时为4位总线,低电平时为8位总线;N表示在低电平时为单行显示,高电平时双行显示;F表示在低电平时显示5×7的点阵字符,高电平时显示5×10的点阵字符。
(7)指令7:字符发生器RAM地址设置。
(8)指令8:DDRAM地址设置。
(9)指令9:读忙信号和光标地址。其中,BF为忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平则表示不忙。
(10)指令10:写数据。
(11)指令11:读数据。
五,LCD1602操作汇总
LCD1602的基本操作分为四种:
读状态:输入RS=0,RW=1,E=高脉冲(上升沿)。输出:D0—D7为状态字。
读数据:输入RS=1,RW=1,E=高脉冲。输出:D0—D7为数据。
写命令:输入RS=0,RW=0,E=高脉冲。输出:无。
写数据:输入RS=1,RW=0,E=高脉冲。输出:无。
六,时钟频率:
在Proteus里面,LCD1602的默认时钟是250KHz 。
七,操作时序:
根据操作时序,给相应IO相应的电平即可。
1,写操作
2,读操作
八,功能简介:
利用51单片机、LCD1602、蜂鸣器,矩阵键盘等构成硬件系统,独立按键开启和关闭计算器,矩阵键盘进行相应的计算。此计算器可以进行多位数的加减乘除。
九,程序源码:
LCD1602 C文件
#include "lcd1602.h"
#include
sbit RS = P2^3; //定义端口
sbit RW = P2^4;
sbit EN = P2^5;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
/*
* 函数名称: LCD uS延时函数
* 参数: 延时数
* 返回值: 无
*/
void delay_us(uchar t)
{
while(--t);
}
/*
* 函数名称: LCD mS延时函数
* 参数: 延时数
* 返回值: 无
*/
void DelayMs(uchar t)
{
while(t--)
{
delay_us(245);
delay_us(245);
}
}
/*
* 函数名称: 判忙函数
* 参数: 无
* 返回值: 无
*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*
* 函数名称: 写入命令函数
* 参数: 命令
* 返回值: 无
*/
void LCD_Write_Com(uchar com)
{
// while(LCD_Check_Busy()); //忙则等待
DelayMs(5);
RS_CLR;
RW_CLR;
EN_CLR;
DataPort= com;
EN_SET;
_nop_();
EN_CLR;
}
/*
* 函数名称: 写入数据函数
* 参数: 数据
* 返回值: 无
*/
void LCD_Write_Data(uchar Data)
{
// while(LCD_Check_Busy()); //忙则等待
DelayMs(5);
RS_SET;
RW_CLR;
EN_CLR;
DataPort= Data;
EN_SET;
_nop_();
EN_CLR;
}
/*
* 函数名称: 清屏函数
* 参数: 无
* 返回值: 无
*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*
* 函数名称:写入字符串函数
* 参数: 坐标,待写字符串
* 返回值: 无
*/
void LCD_Write_String(uchar x,uchar y,uchar *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data(*s);
s ++;
}
}
/*
* 函数名称:Calc写入字符串函数
* 参数: 坐标,待写字符串
* 返回值: 无
*/
void LCD_Calc_String(uchar posx,uchar posy,uchar *str)
{
LCD_Write_Com(0x04);
if (posy == 0)
{
LCD_Write_Com(0x80 + posx);
}
else
{
LCD_Write_Com(0xC0 + posx);
}
while (*str=='\0')
{
LCD_Write_Data(*str);
str ++;
}
}
/*
* 函数名称:写入字符函数
* 参数: 坐标,待写字符
* 返回值: 无
*/
void LCD_Write_Char(uchar x,uchar y,uchar Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*
* 函数名称:初始化函数
* 参数: 坐标,待写字符
* 返回值: 无
*/
void LCD_Init(void)
{
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08);
LCD_Write_Com(0x01);
LCD_Write_Com(0x06);
DelayMs(5);
LCD_Write_Com(0x0F);
}
LCD1602 头文件
#ifndef __LCD1602_H
#define __LCD1602_H
#include "reg51.h"
#define uint unsigned int
#define uchar unsigned char
void LCD_Write_Com(uchar com);
void LCD_Write_Data(uchar Data);
void LCD_Clear(void);
void LCD_Write_String(uchar x,uchar y,uchar *s);
void LCD_Write_Char(uchar x,uchar y,uchar Data);
void LCD_Init(void);
void LCD_Calc_String(uchar posx,uchar posy,uchar *str);
void DelayMs(uchar t);
void delay_us(uchar t);
#endif
主函数:
#include "reg51.h"
#include "lcd1602.h"
#include
#define uchar unsigned char
#define uint unsigned int
sbit BEEP=P3^6;
sbit LED=P3^5;
sbit DISPLAY=P3^2;
/***********************************函数声明区**********************************/
void ButtonScan(void);
void ALL_Init(void);
void delay_ms(uint i);
void ECHO_Result(void);
void Compare_Result(uchar result);
/***********************************函数声明区END**********************************/
#define UNSEAL 0
uchar code dat1[]={0,1,2,3,4,5,6,7,8,9,0x2b-0x30,0x2d-0x30,0x2a-0x30,0x2f-0x30,0x3d-0x30,0x43-0x30};
//回显数据容量根据宏定义修改
#define VOLUME 2
typedef struct _CALC
{
uchar symbol;
uchar symbolFlag;
uchar keyValue;
uchar num;
uchar count;
uchar n;
uchar pointBit;
uchar buttonFlag;
uchar time;
uchar displayFlag;
uchar str[10];
float saveDat[VOLUME][VOLUME];
long dat[3];
}CALC;
CALC calc;
#if UNSEAL
void ECHO_Result(void)
{
uchar j=0;
for(j=0;j<calc.count;j++)
{
LCD_Clear();
LCD_Write_String(0,0," ECHO Results: ");
LCD_Write_String(0,1,(uchar *)&calc.saveDat[j]);
delay_ms(1000);
}
}
#endif
/*
* 函数名称:延时函数
* 参数: 延时数
* 返回值: 无
*/
void delay_ms(uint i)
{
uint j=0;
uint n=0;
for(j=0;j<i;j++)
for(n=0;n<=118;n++);
}
/*
* 函数名称:按键扫描处理函数
* 参数: 无
* 返回值: 无
*/
void ButtonScan(void)
{
P1=0xfe;
if(P1!=0xfe)
{
delay_ms(10);
if(P1!=0xfe)
{
calc.buttonFlag=1;
calc.keyValue=P1&0xf0;
switch(calc.keyValue)
{
case 0xe0: calc.num=7;break;
case 0xd0: calc.num=8;break;
case 0xb0: calc.num=9;break;
case 0x70: calc.num=13;break;
}
}
while(P1!=0xfe);
LCD_Write_Data(0x30+dat1[calc.num]);
}
P1=0xfd;
if(P1!=0xfd)
{
delay_ms(10);
if(P1!=0xfd)
{
calc.buttonFlag=1;
calc.keyValue=P1&0xf0;
switch(calc.keyValue)
{
case 0xe0: calc.num=4;break;
case 0xd0: calc.num=5;break;
case 0xb0: calc.num=6;break;
case 0x70: calc.num=12;break;
}
}
while(P1!=0xfd);
LCD_Write_Data(0x30+dat1[calc.num]);
}
P1=0xfb;
if(P1!=0xfb)
{
delay_ms(10);
if(P1!=0xfb)
{
calc.buttonFlag=1;
calc.keyValue=P1&0xf0;
switch(calc.keyValue)
{
case 0xe0: calc.num=1;break;
case 0xd0: calc.num=2;break;
case 0xb0: calc.num=3;break;
case 0x70: calc.num=11;break;
}
}
while(P1!=0xfb);
LCD_Write_Data(0x30+dat1[calc.num]);
}
P1=0xf7;
if(P1!=0xf7)
{
delay_ms(10);
if(P1!=0xf7)
{
calc.buttonFlag=1;
calc.keyValue=P1&0xf0;
switch(calc.keyValue)
{
case 0xe0: calc.num=15;break;
case 0xd0: calc.num=0;break;
case 0xb0: calc.num=14;break;
case 0x70: calc.num=10;break;
}
}
while(P1!=0xf7);
LCD_Write_Data(0x30+dat1[calc.num]);
}
if(calc.buttonFlag==1)
{
LED=0;
}
if(calc.buttonFlag==1)
{
switch(calc.num)
{
case 0:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 1:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 2:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 3:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 4:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 5:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 6:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 7:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 8:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 9:
if(calc.symbolFlag==0)
{
calc.dat[0]=calc.dat[0]*10+dat1[calc.num];
}
else
{
calc.dat[1]=calc.dat[1]*10+dat1[calc.num];
}
break;
case 10:
{
calc.symbolFlag=1;
calc.symbol=1;
}
break;
case 11:
{
calc.symbolFlag=1;
calc.symbol=2;
}
break;
case 12:
{
calc.symbolFlag=1;
calc.symbol=3;
}
break;
case 13:
{
calc.symbolFlag=1;
calc.symbol=4;
}
break;
case 15:
calc.dat[0]=0;
calc.dat[1]=0;
calc.symbolFlag=0;
calc.symbol=0;
LCD_Clear();
LCD_Write_String(0,0," My Calculate");
LCD_Write_Com(0x0F);
LCD_Write_Com(0xc0);
LED=1;
BEEP=1;
TR0=0;
TR1=0;
break;
case 14:
// LCD_Clear(); //清屏指令
BEEP=1;
TR0=1;
LCD_Write_Com(0x0C);
LCD_Write_Com(0x4f+0x80);
LCD_Write_Com(0x04);
//Omit here
LCD_Write_Data(0);
calc.dat[0]=0;
calc.dat[1]=0;
calc.symbolFlag=0;
calc.count++;
calc.symbol=0;
break;
}
}
calc.buttonFlag=0;
}
void ALL_Init(void)
{
LCD_Init();
calc.keyValue=0;
calc.num=0;
calc.symbolFlag=0;
calc.symbol=0;
calc.dat[0]=0;
calc.dat[1]=0;
calc.dat[2]=0;
calc.count=0;
calc.displayFlag=0;
calc.n=0;
calc.time=0;
LED=1;
IT0=1;
EX0=1;
IT1=1;
EX1=1;
PX1=1;
BEEP=1;
TMOD =0X11;
ET0=1;
ET1=1;
EA=1;
TR0=0;
TR1=0;
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
TH1=(65535-500)/256;
TL1=(65535-500)%256;
LCD_Write_String(0,0," ? Calc Whether");
LCD_Write_String(0,1," or not to open");
while(0==calc.displayFlag);
LCD_Clear();
LCD_Write_String(0,0," My Calculate");
LCD_Write_Com(0xc0);
}
int main(void)
{
ALL_Init();
while(1)
{
if(calc.displayFlag==1)
ButtonScan();
else
for(;;);
}
return 0;
}
void inter0(void)interrupt 0 using 0
{
LCD_Clear();
LCD_Write_String(0,0," My Calculate");
LCD_Write_String(0,1," OPEN ");
calc.displayFlag=1;
}
void inter1(void)interrupt 1 using 1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
BEEP=!BEEP;
}
void inter2(void)interrupt 2 using 3
{
LCD_Clear();
LCD_Write_Com(0x0F);
TR0=0;
TR1=0;
LCD_Write_String(0,1," My Calculate");
LCD_Write_String(0,0," CLOSE ");
calc.displayFlag=0;
}
void inter3(void)interrupt 3 using 2
{
TH1=(65535-500)/256;
TL1=(65535-500)%256;
BEEP=!BEEP;
}
十,Proteus仿真图:
1,上电显示:
2,执行加法仿真效果图:
3,执行减法仿真效果图:
3,执行乘法仿真效果图:
4,执行除法仿真效果图:
5,当除数为零时,蜂鸣报警,效果图如下: