0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

LCD1602液晶显示屏的驱动设计与实现

CHANBAEK 来源:木南创智 作者:尹家军 2022-12-08 11:24 次阅读

LCD1602是一种工业字符型液晶,能够同时显示16x02即32个字符。LCD1602液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,即可以显示出图形。在这一章我们就来讨论LCD1602液晶显示屏驱动的设计与实现。

1、功能概述

  LCD1602液晶又被称作1602字符型液晶,这是一种只用来显示字母、数字、符号等的点阵型液晶模块。LCD1602里面存储器一般有三种:CGROM、CGRAMDDRAM。其中DDRAM(Display Data RAM)就是显示数据RAM,用来寄存待显示的字符代码。共80个字节,其地址和屏幕的对应关系如下如图所示:

  LCD1602使用三条控制线:EN、RW、RS。 其中EN的作用其实就是中线的功能,RW和RS指示了读、它写的是写的方向和内容。在读数据(或者Busy标志)期间,EN线必须保持高电平;而在写指令(或者数据)过程中,EN线上必须送出一个正脉冲。RW、RS的组合一共有四种情况,分别对应四种操作:

  (1)、RS=0、RW=0——表示向LCD写入指令。

  (2)、RS=0、RW=1——表示读取Busy标志。

  (3)、RS=1、RW=0——表示向LCD写入数据。

  (4)、RS=1、RW=1——表示从LCD读取数据。

  LCD1602利用指令码来区分不同的操作,主要的有两类:一是用于初始化配置的指令码;二是用于数据控制的指令码。第一类用于LCD初始化配置的指令码基本上都是在系统启动时,用于对LCD1602的一次性配置。而第二类数据操作的指令码主要用于设置数据指针的位置,现实信息的实现与清楚等。这两类指令码从使用上并无太大区别,后续我们将详细说明。

2、驱动设计与实现

  我们已经了解了LCD1602的基本情况,接下来我们将给予对LCD1602的基本了解设计LCD602的驱动程序。

2.1、对象定义

  在使用一个对象之前我们需要获得一个对象。同样的我们想要LCD1602液晶显示屏就需要先定义LCD1602液晶显示屏的对象。

2.1.1、对象的抽象

  我们要得到LCD1602液晶显示屏对象,需要先分析其基本特性。一般来说,一个对象至少包含两方面的特性:属性与操作。接下来我们就来从这两个方面思考一下LCD1602液晶显示屏的对象。

  先来考虑属性,作为属性肯定是用于标识或记录对象特征的东西。我们来考虑LCD1602液晶显示屏对象属性。对于LCD1602显示屏,它主要的功能就是显示信息,为了标识当前的状态,我们将状态寄存器的值作为对象的属性。

  接着我们还需要考虑LCD1602液晶显示屏对象的操作问题。首先我们需要控制LCD1602的3个控制引脚以实现对LCD1602的控制,但这些控制引脚的操作都与具体的操作平台相关,所以我们将其作为对象的操作来实现。同样的我们还需要向LCD1602发送命令和数据以及从LCD1602获取消息,而读取和发送都是依赖于具体的操作平台的所以我们将其作为LCD1602的两个操作。我们对LCD1602进行操作,免不了要进行时序控制,所以我们需要有延时操作,但我们都明白演示操作依赖于具体的软硬件平台,所以我们将延时处理函数也作为对象的操作。

  根据上述我们对LCD1602液晶显示屏的分析,我们可以定义LCD1602液晶显示屏的对象类型如下:

/* 定义LCD1602的对象类型 */
typedef struct LCD1602Object {
  uint8_t status;
  LCD1602PinSetType *PinHandle;
  void(*SendByte)(uint8_t data);
  uint8_t(*GetByte)(void);
  void (*Delayus)(volatile uint32_t period);    //微秒延时函数
  void (*Delayms)(volatile uint32_t nTime);     //毫秒秒延时函数
}LCD1602ObjectType;

2.1.2、对象初始化

  我们知道,一个对象仅作声明是不能使用的,我们需要先对其进行初始化,所以这里我们来考虑LCD1602液晶显示屏对象的初始化函数。一般来说,初始化函数需要处理几个方面的问题。一是检查输入参数是否合理;二是为对象的属性赋初值;三是对对象作必要的初始化配置。据此我们设计LCD1602液晶显示屏对象的初始化函数如下:

/*对显示屏作初始化配置*/
void LCD1602Initialization(LCD1602ObjectType *lcd,              //LCD1602对象指针
                           LCD1602PinSetType *PinHandle,         //控制引脚操作函数指针数组
                           LCD1602SendByteType sendByte,        //发送一个字节函数指针
                           LCD1602GetByteType getByte,          //读取一个字节函数指针
                           LCD1602DelayType delayus,            //微秒延时函数指针
                           LCD1602DelayType delayms             //毫秒延时函数指针
                             )
{
  if((lcd==NULL)||(PinHandle==NULL)||(sendByte==NULL)||(getByte==NULL)||(delayus==NULL)||(delayms==NULL))
  {
    return;
  }
  
  lcd->PinHandle=PinHandle;
  lcd->SendByte=sendByte;
  lcd->GetByte=getByte;
  lcd->Delayus=delayus;
  lcd->Delayms=delayms;
  
  lcd->Delayus(15);
  WriteCommandToLCD1602(lcd,0x38);
  lcd->Delayms(5);
  WriteCommandToLCD1602(lcd,0x38);
  lcd->Delayms(5);
  WriteCommandToLCD1602(lcd,0x38);
  
  /*后续需要检测BUSY,等待10Mms*/
  lcd->Delayms(10);
  WriteCommandToLCD1602(lcd,0x38);//显示模式设置
  lcd->Delayms(10);
  WriteCommandToLCD1602(lcd,0x08);//显示关闭
  lcd->Delayms(10);
  WriteCommandToLCD1602(lcd,0x01);//显示清屏
  lcd->Delayms(10);
  WriteCommandToLCD1602(lcd,0x06);//显示光标移动位置
  lcd->Delayms(10);
  WriteCommandToLCD1602(lcd,0x0C);//显示开及光标设置

  lcd->PinHandle[LCD1602_EN](Low);
  
  lcd->status=ReadStatusFromLCD1602(lcd);
}

2.2、对象操作

我们已经完成了LCD1602液晶显示屏对象类型的定义和对象初始化函数的设计。但我们的主要目标是获取对象的信息,接下来我们还要实现面向LCD1602液晶显示屏的各类操作。

2.2.1、读数据操作

  我们需要从LCD1602液晶显示屏获取一定的数据,包括读取状态信息和数据信息,唯一的区别只是RS控制引脚的电平,其他的操作都一样,读取数据的时序图如下所示:

  根据我们前面的描述及上面的时序图,我们可以实现获取状态信息及数据的操作函数如下:

/*从LCD1602读状态*/
static uint8_t ReadStatusFromLCD1602(LCD1602ObjectType *lcd)
{
  uint8_t status;
  lcd->PinHandle[LCD1602_RS](Low);
  lcd->PinHandle[LCD1602_RW](High);
  lcd->PinHandle[LCD1602_EN](High);
  
  lcd->Delayus(20);
  status=lcd->GetByte();
  lcd->PinHandle[LCD1602_EN](Low);
  lcd->Delayus(5);
  return status;
}
/*从LCD1602读数据*/
static uint8_t ReadDataFromLCD1602(LCD1602ObjectType *lcd)
{
  uint8_t data;
  lcd->PinHandle[LCD1602_RS](High);
  lcd->PinHandle[LCD1602_RW](High);
  lcd->PinHandle[LCD1602_EN](High);
  
  lcd->Delayus(20);
  data=lcd->GetByte();
  lcd->PinHandle[LCD1602_EN](Low);
  lcd->Delayus(5);
  return data;
}

2.2.2、写数据操作

  我们想要在LCD1602显示屏上显示我们想要的消息就需要向LCD1602显示屏发送命令和数据。发送数据和发送命令的区别仅是RS控制引脚的操作电平不同,具体的操作时序如下所示:

/*向LCD1602写指令*/
static void WriteCommandToLCD1602(LCD1602ObjectType *lcd,uint8_t command)
{
  lcd->PinHandle[LCD1602_RS](Low);
  lcd->PinHandle[LCD1602_RW](Low);

  lcd->SendByte(command);

  lcd->PinHandle[LCD1602_EN](High);
  lcd->Delayus(20);
  lcd->PinHandle[LCD1602_EN](Low);
  lcd->Delayus(5);
}
/*向LCD1602写数据*/
static void WriteDatatoLCD1602(LCD1602ObjectType *lcd,uint8_t data)
{
  lcd->PinHandle[LCD1602_RS](High);
  lcd->PinHandle[LCD1602_RW](Low);

  lcd->SendByte(data);

  lcd->PinHandle[LCD1602_EN](High);
  lcd->Delayus(20);
  lcd->PinHandle[LCD1602_EN](Low);
  lcd->Delayus(5);
}

3、驱动的使用

  我们已经实现了LCD1602液晶显示屏驱动程序,在接下来我们还需要设计一个简单的应用验证这一驱动设计是否正确。

3.1、声明并初始化对象

  使用基于对象的操作我们需要先得到这个对象,所以我们先要使用前面定义的LCD1602液晶显示屏对象类型声明一个LCD1602液晶显示屏对象变量,具体操作格式如下:

  LCD1602ObjectType lcd;

  声明了这个对象变量并不能立即使用,我们还需要使用驱动中定义的初始化函数对这个变量进行初始化。这个初始化函数所需要的输入参数如下:

LCD1602ObjectType *lcd,              //LCD1602对象指针
LCD1602PinSetType *PinHandle,         //控制引脚操作函数指针数组
LCD1602SendByteType sendByte,        //发送一个字节函数指针
LCD1602GetByteType getByte,          //读取一个字节函数指针
LCD1602DelayType delayus,            //微秒延时函数指针
LCD1602DelayType delayms             //毫秒延时函数指针

  对于这些参数,对象变量我们已经定义了。主要的是我们需要定义几个函数,并将函数指针作为参数。这几个函数的类型如下:

/*定义引脚操作函数指针类型*/
typedef void (*LCD1602PinSetType)(uint8_t value);
/*定义发送一个字节操作函数指针*/
typedef void(*LCD1602SendByteType)(uint8_t data);
/*定义读取一个字节操作函数指针*/
typedef uint8_t(*LCD1602GetByteType)(void);
/*定义延时操作函数指针*/
typedef void (*LCD1602DelayType)(volatile uint32_t time);

  对于这几个函数我们根据样式定义就可以了,具体的操作可能与使用的硬件平台有关系。控制引脚的操作函数实际是3个,组成一个函数指针数组,分别对应RS、RW、EN控制引脚。具体函数定义如下:

LCD1602PinSetType pinSets[3]={RsPinOperation,RwPinOperation,EnPinOperation};

/*RS控制引脚操作*/
static void RsPinOperation(uint8_t value)
{
  HAL_GPIO_WritePin(GPIOD,GPIO_PIN_7,(GPIO_PinState)value);
}

/*RW控制引脚操作*/
static void RwPinOperation(uint8_t value)
{
  HAL_GPIO_WritePin(GPIOD,GPIO_PIN_8,(GPIO_PinState)value);
}

/*EN控制引脚操作*/
static void EnPinOperation(uint8_t value)
{
  HAL_GPIO_WritePin(GPIOD,GPIO_PIN_9,(GPIO_PinState)value);
}

/*从LCD1602读一个字节*/
static uint8_t ReadByteFromLCD(void)
{
  uint8_t data=0;
  
  data=(uint8_t)(GPIOD->IDR);
  
  return data;
}
                               
/*向LCD1602写一个字节*/
static void WriteByteToLCD(uint8_t data)
{
  uint16_t value=GPIOD->ODR;
  
  value=(value&&0xFF00)||data;
  
  GPIOD->ODR=value;
}

  对于延时函数我们可以采用各种方法实现。我们采用的STM32平台和HAL库,所以毫秒延时函数可以直接使用HAL_Delay()函数。微秒延时函数采用我们编写的delayus于是我们可以调用初始化函数如下:

LCD1602Initialization(&lcd,              //LCD1602对象指针
                 pinSets,         //控制引脚操作函数指针数组
                 WriteByteToLCD,        //发送一个字节函数指针
                 ReadByteFromLCD,          //读取一个字节函数指针
                 Delayus,            //微秒延时函数指针
                 HAL_Delay             //毫秒延时函数指针
               );

3.2、基于对象进行操作

  我们定义了对象变量并使用初始化函数给其作了初始化。接着我们就来考虑操作这一对象获取我们想要的数据。我们在驱动中已经将获取数据并转换为转换值的比例值,接下来我们使用这一驱动开发我们的应用实例。

/*在LCD1602中显示数据*/
void LCD1602Display(void)
{
  float temp=20.5;
  float pres=101.35;
  float humi=34.6;
  
  LCD1602DisplayClear(&lcd,LCD1602_AllLine),
  
  Lcd1602ContentDisplay(&lcd,0x80, "T%0.1fC,P%0.1fKPa,H%0.1f%%", temp,pres, humi);
  Lcd1602ContentDisplay(&lcd,0xC0, "T%0.1fC,P%0.1fKPa,H%0.1f%%", temp,pres, humi);
}

  我们将显示器清屏,然后再每一行都显示温度、压力和湿度数据。

4、应用总结

  我们已经设计并实现了LCD1602的驱动程序,并在此基础上设计了简单的验证应用。我们可以正常读写LCD1602显示屏,并且在LCD1602显示屏正确心事我们想要的信息,说明我们的驱动设计是没有问题的。

  在使用驱动时,有一点需要注意。因为在初始化函数中,对控制引脚的操作采用的时函数指针数组,但这个数组元素的顺序不是随意的,而是必须与枚举类型LCD1602PinType中定义的顺序一致才能正确操作。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 显示屏
    +关注

    关注

    28

    文章

    4483

    浏览量

    74238
  • 驱动设计
    +关注

    关注

    1

    文章

    111

    浏览量

    15285
  • LCD1602
    +关注

    关注

    14

    文章

    607

    浏览量

    52576
  • 液晶显示屏
    +关注

    关注

    1

    文章

    208

    浏览量

    27386
收藏 人收藏

    评论

    相关推荐

    怎样使用单片机去控制LCD1602液晶显示屏显示时间等信息

    怎样使用单片机去控制LCD1602液晶显示屏显示时间等信息?如何对基于单片机的LCD1602液晶显示屏进行仿真?
    发表于 09-01 06:14

    STM32是怎样去控制LCD1602液晶显示屏

    LCD1602的常用指令有多少啊?STM32是怎样去控制LCD1602液晶显示屏的?
    发表于 12-15 06:30

    请问如何驱动LCD1602液晶显示屏

    LCD1602液晶显示屏的原理是什么?如何驱动LCD1602液晶显示屏
    发表于 01-17 08:29

    LCD1602液晶显示屏的操作流程是怎样的呢

    什么是LCD1602液晶显示屏呢?LCD1602液晶显示屏的操作流程是怎样的呢?
    发表于 01-26 06:32

    如何对LCD1602液晶显示屏进行编程呢

    LCD1602液晶显示屏的引脚功能有哪些呢?如何对LCD1602液晶显示屏进行编程呢?
    发表于 01-26 08:26

    STM32是怎样通过IIC去控制LCD1602液晶显示屏的呢

    LCD1602常用指令有哪些呢?STM32是怎样通过IIC去控制LCD1602液晶显示屏的呢?
    发表于 01-26 07:44

    液晶显示模块LCD1602应用

    液晶显示模块LCD1602应用
    发表于 09-25 16:58 683次下载
    <b class='flag-5'>液晶显示</b>模块<b class='flag-5'>LCD1602</b>应用

    基于ARM的LCD1602液晶显示源代码

    基于ARM的LCD1602液晶显示源代码。
    发表于 05-20 16:29 18次下载

    lcd1602显示原理,LCD1602液晶显示器的分类有哪些?

    LCD1602是一种工业字符型液晶,能够同时显示16x02即32个字符。LCD1602液晶显示原理 LC
    发表于 10-20 10:32 3.6w次阅读

    使用51单片机控制LCD1602液晶显示屏的程序资料免费下载

    本文档的主要内容详细介绍的是使用51单片机控制LCD1602液晶显示屏的程序资料免费下载。
    发表于 01-08 08:00 33次下载
    使用51单片机控制<b class='flag-5'>LCD1602</b><b class='flag-5'>液晶显示屏</b>的程序资料免费下载

    LCD1602液晶显示屏的基础驱动程序免费下载

    本文档的主要内容详细介绍的是LCD1602液晶显示屏的基础驱动程序免费下载。
    发表于 08-16 17:32 17次下载
    <b class='flag-5'>LCD1602</b><b class='flag-5'>液晶显示屏</b>的基础<b class='flag-5'>驱动</b>程序免费下载

    使用51单片机设计液晶显示屏LCD1602显示的计算器程序免费下载

    本文的主要内容是使用51单片机设计液晶显示屏LCD1602显示的计算器程序免费下载。
    发表于 06-26 17:43 20次下载
    使用51单片机设计<b class='flag-5'>液晶显示屏</b><b class='flag-5'>LCD1602</b><b class='flag-5'>显示</b>的计算器程序免费下载

    lcd1602液晶显示屏介绍_lcd1602引脚功能

    本文首先阐述了lcd1602液晶显示屏的概念,其次阐述了LCD1602外形尺寸,最后介绍了lcd1602引脚功能。
    发表于 04-23 08:53 7.1w次阅读

    LCD1602显示屏的资料合集免费下载

    LCD1602显示屏的资料合集免费下载包括了:LCD1602显示屏技术手册,库文件,Arduino参考程序,1602基本
    发表于 05-27 08:00 59次下载
    <b class='flag-5'>LCD1602</b><b class='flag-5'>显示屏</b>的资料合集免费下载

    基于FPGA的LCD1602液晶显示模块驱动设计

    本文通过以LCD1602液晶显示模块为基础,介绍FPGA驱动LCD1602原理,详细介绍硬件原理图设计及FPGA驱动
    的头像 发表于 10-24 14:42 1084次阅读
    基于FPGA的<b class='flag-5'>LCD1602</b><b class='flag-5'>液晶显示</b>模块<b class='flag-5'>驱动</b>设计