Skip to content

LCD1602显示器

作者:姜蘅洋

1.LCD1602介绍:

image-20230610205423081

  • LCD1602是一个LCD的显示器:
    • LCD的英文:Liquid Crystal Display,即液晶显示器。
    • LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。
      • 每个字符位由一个5 x 8的点阵组成,通过点阵的亮灭组合形成字符。
      • 其中,1602表示该显示器的分辨率是16 x 2,即每行显示16个字符,一共可以显示两行字符。
      • 每个字符位之间有一定的间隔,两行之间也有一定的间隔。
  • LCD1602的工作环境:
    • 工作电压:4.5~5V
    • 工作电流:2.0mA
    • 工作温度:-20°C~70°C
  • LCD1602的引脚说明:
    • 16Pin:
    • image-20230610204210472
    • 固定引脚
      • Pin_1:VSS电源地。
      • Pin_2:VDD电源正极。
      • Pin_15:BLA背光源正极。
      • Pin_16:BLK背光源负极。
    • 配置引脚
      • VL:液晶显示偏压信号。
        • 调整LCD1602的显示对比度,引脚电压为0时可以得到最高的对比度。
      • RS:数据命令选择端。
        • RS = 1的时候,输入字节当做数据处理。
        • RS = 0的时候,输入字节当做命令处理。
      • R/W:读写选择端。
        • 当R/W = 1的时候,执行读操作,即单片机从LCD1602中读数据。
        • 当R/W = 0的时候,执行写操作,即单片机向LCD1602中写数据。
          • LCD1602固定执行显示功能:
            • 我们只需要让LCD1602显示字符,即向LCD1602中写入数据,不需要从LCD1602中读取数据。
      • E:使能信号。
        • 本质上来讲是LCD1602 的数据控制时钟信号。
      • D0 ~ D7:数据字节或命令字节。
        • 8 位并行数据口

2.LCD1602的驱动程序:

  • 单片机驱动程序:

    • 在单片机领域,外设驱动程序是指单片机控制操作外部设备的软件组件
      • 驱动程序定义了单片机和外设的通信方式(也就是时序问题)。
  • 根据外设时序图编写外设驱动程序:

    • 写时序:以写命令字节为例。

      • 写数据的时候只需要把RS置为高电平即可。

      • image-20230610212235481

      • 由于是写命令,因此在整个写时序中:

        • 把RS设置为0,即输入字节当做命令处理。
        • 把R/W设置为0,即执行写入操作。
      • 相应的我们只需要考虑E和D的时序:

        • 标点:开始点、转折点、结束点

          • image-20230610215359264
        • 时序参数:

          • image-20230610215432830
        • A点:E = 0,A点和B点之间没有信号更改,不需要延时。

        • B点:B点数据载入寄存器,B点和C点之间有一个跳变延时,对于这种跳变,我们不需要延时。

        • C点:数据载入完成,C点和D点之间有一个tsp2的延时,由于该延时的最小值是40ns,没有最大值限制,由于我们的单片机是us级别(周期是90us左右)的,因此延时设置10us即可。

            • 10us延时的原因是:STC-ISP计时软件能生成最小的延时函数是10us,当然STC89C52的机器周期是1us(对应的频率是1MHz)。

              • c
                void LCD_DriverDelay()		//@11.0592MHz
                {
                	unsigned char data i;
                
                	i = 2;
                	while (--i);
                }
        • D点:E = 1,同时D点和E点之间有一个延时tR,这个延时没有最小值限制,因此不延时。

        • E点:信号线E到达高电平,即开始稳定的发送数据,E点和F点之间的延时tPW的最小值是150ns,这里我们设置10us。

        • F点:E = 0,同时F点和G点之间有一个延时tF,这个延时没有最小值限制,因此不延时。

        • G点:信号线E到达低电平,G点和H点之间有一个延时tHD2,这个延时的最小值是20ns,这里我们设置为10us。

        • H点:一个写时序周期完成,后面的点是下一个写时序的点。

      • 查看原理图:

        • image-20230610223715554
        • image-20230610223757338
      • 驱动代码:

        • c
          void LCD1602_Write_Command(uint_8 command)
          {
          	RS = 0;
          	WR = 0;
          	LCD_EN = 0;
          	Write_Byte = command;
          	LCD_WriteDriverDelay_10us();
          	LCD_EN = 1;
          	LCD_WriteDriverDelay_10us();
          	LCD_EN = 0;
          	LCD_WriteDriverDelay_10us();
          }
        • 该代码和上面的分析完全对应。

    • 初始化:

      • 我们在使用外设之前,必须要初始化。
      • 初始化LCD1602的时序说明:
        • image-20230611114000611

        • 显示模式设置指令:

          • 0x38:设置16 x 2显示,5 x 7点阵,8位数据接口。
        • 显示清屏:

          • 0x01:数据地址指针清0,所有显示清0。
        • 显示回车:

          • 0x02:数据地址指针清0。
        • 显示光标移动设置:

          • 0x04:写一个字符后,地址指针减1,且光标减1,整屏显示不移动。
          • 0x05:写一个字符后,地址指针减1,且光标减1,整屏显示右移。
          • 0x06:写一个字符后,地址指针加1,且光标加1,整屏显示不移动。
          • 0x07:写一个字符后,地址指针加1,且光标加1,整屏显示左移。
        • 显示开关及光标位置:

          • 0x08:显示关闭。
          • 0x0F:显示光标并且光标闪烁。
          • 0x0E:显示光标但光标不闪烁。
          • 0xC0:不显示光标。
          • 这里还要注意,由于P0端口复用,因此我们要失能控制数码管的74HC573的Latch Enable:
            • image-20230611084551927
        • 初始化代码:

          • c
            void LCD1602_Init(void)
            {
            	DULA=0;
            	WELA=0;
            	LCD1602_Write_Command(0x38); 
            	LCD_InitDriverDelay_5ms();
            	LCD1602_Write_Command(0x0C); 
            	LCD_InitDriverDelay_5ms();  
            	LCD1602_Write_Command(0x06);
            	LCD_InitDriverDelay_5ms(); 
            	LCD1602_Write_Command(0x01);
            	LCD_InitDriverDelay_5ms(); 
            }
    • 显示字符:

      • LCD1602控制器内部带有80字节的RAM缓冲区,每个字节存储的值用来使点阵屏显示字符。
        • 对应关系:
          • image-20230611093253359
          • 多出来的字节:
            • 正常来讲,对于16 x 2的LCD屏,有32个字节即可。
            • 多出来的字节的目的是满足上面不同的显示光标移动设置
      • LCD1602控制器内部有一个数据地址指针,可以通过这个指针访问全部的80字节RAM。
        • image-20230611093728284
        • 例如:
          • 指令码是0x80,那么数据地址指针指代的就是第一行第一列,接下来我们向这个点阵中写入字符。
          • 指令码是0x80 + 0x40,那么数据地址指针指代的就是第一行第二列,接下来我们向这个点阵中写入字符。
          • 我们不用每写入一个字符就手动改变数据地址指针的位置,在显示光标移动设置中会设置自动改变数据地址指针的位置。
    • 字符表:

      • image-20230611100339143
      • 标准字符表符合ASCII编码

3.LCD1602实验:

  • c
    //lcd1602.h
    #ifndef __LCD1602_H__
    #define __LCD1602_H__
    #include "overwhelm.h"
    #include <intrins.h>
    #define RS P3_5
    #define WR P3_6
    #define LCD_EN P3_4
    #define DULA P2_6
    #define WELA P2_7
    #define Write_Byte P0
    void LCD_Write_Line(uint_8 Command,uint_8 *str);
    void LCD1602_Init(void);
    #endif
  • c
    //lcd1602.c
    #include "lcd1602.h"
    void LCD_WriteDriverDelay_10us()		//@11.0592MHz
    {
    	unsigned char data i;
    
    	i = 2;
    	while (--i);
    }
    void LCD_InitDriverDelay_5ms(void)		//@11.0592MHz
    {
    	unsigned char data i, j;
    
    	i = 9;
    	j = 244;
    	do
    	{
    		while (--j);
    	} while (--i);
    }
    void LCD1602_Write_Command(uint_8 command)
    {
    	RS = 0;
    	WR = 0;
    	LCD_EN = 0;
    	Write_Byte = command;
    	LCD_WriteDriverDelay_10us();
    	LCD_EN = 1;
    	LCD_WriteDriverDelay_10us();
    	LCD_EN = 0;
    	LCD_WriteDriverDelay_10us();
    }
    
    void LCD1602_Write_Data(uint_8 dat)
    {
    	RS = 1;
    	WR = 0;
    	LCD_EN = 0;
    	Write_Byte = dat;
    	LCD_WriteDriverDelay_10us();
    	LCD_EN = 1;
    	LCD_WriteDriverDelay_10us();
    	LCD_EN = 0;
    	LCD_WriteDriverDelay_10us();
    }
    
    void LCD1602_Init(void)
    {
    	DULA=0;
    	WELA=0;
    	LCD1602_Write_Command(0x38); 
    	LCD_InitDriverDelay_5ms();
    	LCD1602_Write_Command(0x0C); 
    	LCD_InitDriverDelay_5ms();  
    	LCD1602_Write_Command(0x06);
    	LCD_InitDriverDelay_5ms(); 
    	LCD1602_Write_Command(0x01);
    	LCD_InitDriverDelay_5ms(); 
    }
    void LCD_Write_Line(uint_8 Command,uint_8 *str)
    {
    	LCD1602_Write_Command(Command);
    	while (*str != '\0')
    	{
    		LCD1602_Write_Data(*str++);
    	}
    }
  • c
    //main.c
    #include "overwhelm.h"
    uint_8 First_lineString[] = "    CCNU-IOT    ";
    uint_8 Second_lineString[] = " We Welcome you!";
    void main(void)
    {
    	LCD1602_Init();
    	LCD_Write_Line(0x80,First_lineString);
    	LCD_Write_Line(0x80 + 0x40,Second_lineString);
    	while (1)
    	{
    		
    	}
    }
  • 实验结果:

    • 5886A47B31EFF22645B0C95F52622AF8

Released under the MIT License.