LCD1602的介绍
LCD1602是一种字符型液晶显示模块,通常用于嵌入式系统、单片机等领域。它由LCD(液晶显示屏)、HD44780控制驱动主电路及其扩展驱动电路、少量电阻、电容元件等组成。
LCD1602具有以下特点和功能:
- 显示能力:LCD1602可以同时显示两行,每行16个字符,共32个字符。
- 控制接口:通常使用8位数据总线D0-D7、RS、R/W、EN三个控制端口进行控制。
- 工作电压:一般工作电压为5V。
- 显示原理:利用液晶的物理特性,通过电压对其显示区域进行控制,从而显示出字符和简单图形。
- 硬件参数:LCD1602主要参数包括工作温度范围、显示区域尺寸、像素尺寸、视角等。
- 引脚功能:LCD1602的引脚包括VCC(电源正极)、GND(电源负极)、V0(液晶对比度调节)、RS(寄存器选择)、R/W(读/写选择)、EN(使能)、D0-D7(数据总线)、A(背光正极)、K(背光负极)等。
工作原理
LCD1602使用HD44780芯片作为控制器,通过与主控芯片(如单片机或微处理器)进行通信来控制液晶显示屏。
工作时,主控芯片向LCD1602发送命令和数据。在发送之前,需要设置RS引脚的电平来区分是发送命令还是发送数据。当RS为高电平时,表示发送的是数据;当RS为低电平时,表示发送的是命令。通过设置RW引脚的电平来区分是写入操作还是读取操作,当RW为高电平时,表示读取操作;当RW为低电平时,表示写入操作;
这里的数据输入是并行输入,操作就是直接将数据传入P0寄存器即可;
在发送命令或数据后,需要通过控制引脚中的E引脚来触发LCD1602对命令或数据进行处理。通过设置E引脚的上升沿或下降沿触发,将数据写入液晶单元并显示相应的内容。
此外,LCD1602通常还包含背光引脚,用于控制显示屏背光的开关。通过控制背光引脚的电平,可以使LCD1602的显示内容在不同的光照条件下更好地被观察到。
上图是内部的大致存储结构;上面说过这是一块字符型的LCD模块;我们输入的数字或者字符,都将通过ASCII码值的转换在字模库中找出对应的码值然后在屏幕进行显示;
时序结构
在时序结构中,我们要做有写数据和写指令的操作;
写指令:RS引脚置于高电平,表示要选择指令;RW置于低电平,表示选择写入;然后将对应的数据给到P0寄存器;最后将使能置高电平,置完需要进行延迟1ms;
输入的数据由控制器芯片将信号传递给液晶模块的每个像素点。延迟操作可以确保驱动信号在传递过程中达到稳定状态;当然LCD1602的也需要一定的响应时间。
写数据:将RS引脚置于低电平,其他操作与写指令一致;
代码:
//引脚定义 sbit LCD_RS=P2^6; sbit LCD_RW=P2^5; sbit LCD_E=P2^7; #define LCD_DATAPORT P0 //延迟1ms函数 void Delay1ms() //@11.0592MHz { unsigned char i, j; _nop_(); i = 2; j = 199; do { while (--j); } while (--i); } //LCD1602写入指令 void LCD_WriteCommand(unsigned char Command) { LCD_RS=0; LCD_RW=0; LCD_DATAPORT=Command; LCD_E=1; Delay1ms(); LCD_E=0; Delay1ms(); } //LCD1602写入数据 void LCD_WriteData(unsigned char Data) { LCD_RS=1; LCD_RW=0; LCD_DATAPORT=Data; LCD_E=1; Delay1ms(); LCD_E=0; Delay1ms(); }
LCD1602操作流程
这里我们只进行初始化和字符显示操作;
初始化:通过写入命令的操作,进行初始化;
void LCD_Init() { LCD_WriteCommand(0x38);//功能设置:八位数据接口两行显示 LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关 LCD_WriteCommand(0x06);//读数据,写入操作后,光标自动加一 LCD_WriteCommand(0x01);//清屏操作 }
字符显示:将DDRAM的地址与写入的行列位置进行按位或,找到对应光标位置;
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char) { if(Line==1) { LCD_WriteCommand(0x80|(Column-1));//0x80|AC ,设置光标位置 } else { LCD_WriteCommand(0x80|(Column-1)+0x40); } LCD_WriteData(Char);//写入数据,一个字符一个字符进行写入 }
原代码
LCD1602.h
#ifndef __LCD1602_H__ #define __LCD1602_H__ LCD_Init(); LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char); void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char* String); void LCD_ShowNum(unsigned char Line,unsigned char Colunm,unsigned int Number,unsigned char lenth); void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char lenth); void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Lenth); void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Lenth); #endif
LCD1602.c
#include <REGX52.H> #include<INTRINS.H> //引脚定义 sbit LCD_RS=P2^6; sbit LCD_RW=P2^5; sbit LCD_E=P2^7; #define LCD_DATAPORT P0 //延迟函数 void Delay1ms() //@11.0592MHz { unsigned char i, j; _nop_(); i = 2; j = 199; do { while (--j); } while (--i); } //LCD1602写命令 void LCD_WriteCommand(unsigned char Command) { LCD_RS=0; LCD_RW=0; LCD_DATAPORT=Command; LCD_E=1; Delay1ms(); LCD_E=0; Delay1ms(); } //LCD1602写数据 void LCD_WriteData(unsigned char Data) { LCD_RS=1; LCD_RW=0; LCD_DATAPORT=Data; LCD_E=1; Delay1ms(); LCD_E=0; Delay1ms(); } //LCD1602初始化函数 void LCD_Init() { LCD_WriteCommand(0x38); LCD_WriteCommand(0x0c); LCD_WriteCommand(0x06); LCD_WriteCommand(0x01); } //LCD1602设置位置 void LCD_SetCursor(unsigned char Line,unsigned char Column) { if(Line==1) { LCD_WriteCommand(0x80|(Column-1)); } else { LCD_WriteCommand(0x80|(Column-1)+0x40); } } //LCD1602显示字符 void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char) { LCD_SetCursor(Line,Column); LCD_WriteData(Char); } //LCD1602显示字符串 void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char* String) { unsigned char i; LCD_SetCursor(Line,Column); //利用循环将一个个字符进行写入,光标会自动加一 for(i=0;String[i]!='\0';i++)//字符串的终止字符'\0' { LCD_WriteData(String[i]); } } //返回值=X的Y次方 int LCD_Pow(int X,int Y) { unsigned char i; int Result=1; for(i=0;i<Y;i++) { Result*=X; } return Result; } //LCD1602显示数字 void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char lenth) { unsigned char i; LCD_SetCursor(Line,Column); for(i=lenth;i>0;i--) { LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10); //通过除和取余进行取数字对应的位数 //由于取得是ASCII码值,对应的数字前面需要增加'0'字符 } } //显示有符号十进制所给数字 void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char lenth) { unsigned char i; unsigned int Number1; LCD_SetCursor(Line,Column); if(Number>=0) { LCD_WriteData('+'); Number1=Number; } else { LCD_WriteData('-'); Number1=-Number; } for(i=lenth;i>0;i--) { LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10); } } //显示以十六进制所给的数字 void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Lenth) { unsigned char i; unsigned char SingleNumber; LCD_SetCursor(Line,Column); for(i=Lenth;i>0;i--) { SingleNumber=Number/LCD_Pow(16,i-1)%16; if(SingleNumber<10) { LCD_WriteData('0'+SingleNumber); } else { LCD_WriteData('A'+SingleNumber-10); } } } //在LCD1602位置显示二进制数字 void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Lenth) { unsigned char i; LCD_SetCursor(Line,Column); for(i=Lenth;i>0;i--) { LCD_WriteData('0'+Number/LCD_Pow(2,i-1)%2); } }
main.c
#include <REGX52.H> #include"LCD1602.h" void main() { LCD_Init(); LCD_ShowBinNum(1,1,10,4); LCD_ShowHexNum(1,6,255,3); LCD_ShowNum(2,1,789,4); }
对于main.c的内容,只是对LCD1602进行测试,读者可以自己进行对应的尝试;