Bootstrap

【STC8A8K64D4开发板】第3-3讲:LCD1602液晶显示模块的应用

第3-3讲:LCD1602液晶显示模块的应用

    1. 学习目的
  1. 了解LCD1602显示模块涉及到的3种存储器:CGROM、CGRAM和DDRAM。
  2. 掌握LCD1602显示模块的显示原理:DDRAM和字符显示区域是如何对应的,写DDRAM时写入的数据和显示的字符如何关联起来的。
  3. 根据LCD1602显示模块的读写时序和指令集,编写LCD1602显示模块的驱动程序。
    1. LCD1602液晶显示模块
      1. LCD1602简介

LCD1602显示模块是一种专门用来显示字母、数字、符号等字符的点阵型液晶模块,因此,他也叫字符型液晶显示模块(以下简称LCD1602)。

LCD1602有8位数据总线D0-D7,和RS、R/W、EN三个控制端口,工作电压为5V。LCD1602中的1602指的是液晶屏每行可以显示16个字符,共有2行,也就是LCD1602最多只能显示16×2=32个字符。

常用的LCD1602有蓝底色白字和黄绿底色黑字,如下图所示。

图1:LCD1602液晶显示模块

他们显示的效果如下图。

图2:LCD1602显示效果

LCD1602模块主要特点如下:

  1. 显示容量:16×2个字符。
  2. 芯片工作电压:+4.8 ~ +5.2V,最佳工作电压为5.0V。
  3. 工作电流(背光除外) 1.7mA(max)。
  4. 工作电流(背光) 24.0mA(max)。
  5. 带有字符对比度调节和背光源。
  6. 模块引脚数量:16个。

LCD1602模块引脚定义如下表所示。

表1:LCD1602液晶显示模块引脚定义

引脚编号

名称

功能描述

1

VSS

5V电源负

2

VDD

5V电源正

3

VO

LCD 驱动电压输入端

4

RS

指令/数据选择信号(低电平选择指令,高电平选择数据)

5

RW

读写选择信号(低电平选择写操作,高电平选择读操作)

6

E

使能信号

7

D0

8位数据总线模式时为数据0,4位总线模式下D0~D3脚断开

8

D1

8位数据总线模式时为数据1,4位总线模式下D0~D3脚断开

9

D2

8位数据总线模式时为数据2,4位总线模式下D0~D3脚断开

10

D3

8位数据总线模式时为数据3,4位总线模式下D0~D3脚断开

11

D4

8位数据总线模式时为数据4,4位总线模式下D0~D3脚断开

12

D5

8位数据总线模式时为数据5,4位总线模式下D0~D3脚断开

13

D6

8位数据总线模式时为数据6,4位总线模式下D0~D3脚断开

14

D7

8位数据总线模式时为数据7,4位总线模式下D0~D3脚断开

15

BLA

背光电源正极

16

BLK

背光电源负极

      1. LCD1602显示原理

学习LCD1602显示原理时,首先需要了解的是LCD1602片内的3种存储器,他们的作用和区别如下:

  1. CGROM(字符发生器 ROM):字模存储空间。液晶屏出厂时将一些标准的字符的字模编码固化到该空间,用户是无法修改的。
  2. CGRAM(字符发生器 RAM):他是用来扩展液晶屏可以显示的内容的,当我们要显示的字符在CGROM中没有,就可以自己设计字模编码,存储到该空间。通常,我们用不到CGRAM。
  3. DDRAM(显示数据寄存器):我们在液晶屏上显示字符,主要就是和他打交道。 显示字符时将字符编码写入到DDROM中和LCD1602显示对应的地址,之后由液晶屏控制器根据字符编码从CGROM中找到对应的字符的字模并显示到液晶屏上。

那么,DDRAM和 LCD1602显示屏上的显示位置和显示内容是怎么对应起来的?换句话说,我知道LCD1602可以显示2行16列共32个字符,我也知道DDRAM中的字符编码决定了显示内容,那么,如果我想在第1行的第5列显示数字“1”,怎么去实现显示?

看下面这张图,为了方便读者观察LCD1602的字符显示区域,特意调整了屏的对比度,可以很明显的看到屏上面分为2行16列共32个字符显示区域。

图3:DDRAM 地址与 LCD 1602显示屏上的显示位置的对应关系

DDRAM的大小是80个字节,其中,地址00H~0FH依次对应LCD1602的第1行的第1列到第16列,地址40H~4FH依次对应LCD1602的第2行的第1列到第16列。可以看到,屏的每一个字符显示区域在DDRAM中都对应一个固定的地址,这个地址中写入的字符编码就决定了该字符显示区域显示的字符。

如果要在第1行的第5列显示数字“1”,只要向DDRAM的地址04H写入数字“1”的编码即可。同理,如果要在第2行的第2列显示字母“A”,只要向DDRAM的地址41H写入字母“A”的编码即可。

写入的字符编码怎么和显示的字模对应起来的?如让LCD1602其中的一个字符显示区域显示数字1,应该向DDRAM对应的地址写入什么内容。

看下面的图片,下图是LCD1602的CGROM出厂时固化的字模。可以看到字符1对应的D0~D7高4位是0011,低4位是0001,组合后是00110001b,对应的16进制为0x31。而0x31正是字符1的ASCII码,对于DDRAM其他的字符,也是一样的,他们对应的D0~D7的数据也都是字符的ASCII码。

由此,我们知道,要在LCD1602的某个字符显示区域显示字符,只需将需要显示的字符的ASCII写入到DDRAM对应的地址即可。

图4:字符码与字模的对应关系

了解了LCD1602的基本显示原理后,接下里需要知道的是LCD1602的读写时序和指令集,这些是和编程直接相关的。通过LCD1602的读写时序,我们能知道如何通过硬件接口将输入发送给LCD1602或从LCD1602读取数据,通过指令集,我们能够知道,让LCD1602实现不同的显示,需要发送什么指令。

      1. LCD1602的读写时序

LCD1602的基本操作分为四种:读状态、读数据、写命令和写数据。

  1. 读状态:输入RS=0,RW=1,E=高脉冲。输出:D0—D7为状态字。
  2. 读数据:输入RS=1,RW=1,E=高脉冲。输出:D0—D7为数据。

LCD1602的读时序如下图所示。

图5:LCD1602读时序

  1. 写命令:输入RS=0,RW=0,E=高脉冲。输出:无。
  2. 写数据:输入RS=1,RW=0,E=高脉冲。输出:无。

LCD1602的写时序如下图所示。

图6:LCD1602写时序

      1. LCD1602指令集

LCD1602共有如下11条指令。

  1. 清屏指令
  1. 指令码:

  1. 功能:清显示,DDRAM的全部空间填入空字符“20H”;地址计数器AC=0;光标归位到01H位置(显示屏左上角)。
  1. 光标归位指令
  1. 指令码:

  1. 功能:地址计数器AC=0;光标归位到01H位置(显示屏左上角);DDRAM内容保持不变。
  1. 进入模式指令
  1. 指令码:

  1. 功能:设置光标、画面移动方式。
  1. I/D =1:完成一个字符码传送后,光标右移,AC自动加1。
  2. I/D =0:完成一个字符码传送后,光标左移,AC自动减1。
  3. S =1:将全部显示向右(I/D=1)或向右(I/D=1)移位。
  4. S =0:显示不移动。
  1. 显示开/关控制指令
  1. 指令码:

  1. 功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。
  1. D =1:开显示;D =0:关显示。关显示后,显示数据仍保存在DDRAM中。
  2. C =1:显示光标;C =0:不显示光标。
  3. B =1:光标闪烁;B =0:光标不闪烁。
  1. 光标或显示移位指令
  1. 指令码:

  1. 功能:设置整屏移位或光标移位。

  1. 功能设置指令
  1. 指令码:

  1. 功能:设置模块数据接口宽度和屏的显示方式。
  1. DL=1:8位数据总线(D0~D7);DL =0:8位数据总线(D4~D7,D0~D3不使用)。
  2. N =1:两行显示;N =0:单行显示。
  3. F =1:5×10点阵加光标显示模式;F =0:5×7点阵加光标显示模式。
  1. 设置CGRAM地址指令
  1. 指令码:

  1. 功能:设定下一个要存入数据的CGRAM的地址。
  1. 设置DDRAM地址指令
  1. 指令码:

  1. 功能:设置 DDRAM 地址指针,设置地址后即可通过写指令将欲显示的字符码写入该地址。
  1. 读忙标志 BF 和 AC
  1. 指令码:

  1. 功能:判忙和获取地址指针内容。
  1. BF=1:模块正在进行内部操作,无法接收任何外部指令和数据,直到 BF=0 为止。
  2. AC6 ~ AC0:地址计数器 AC 内的当前内容,由于地址计数器 AC 为CGROM、CGRAM 和 DDRAM公用,因此当前 AC 内容所指区域由前一条指令操作区域决定;故只有 BF=0 时,送到 DB7 ~ DB0 的数据AC6 ~ AC0 才有效。
  1. 向DDRAM或CGRAM写入数据
  1. 指令码:

  1. 功能:将用户自定义字符的字模数据写到已经设置好的 CGRAM 的地址中,或者是将欲显示字符的字符码写到DDRAM 中。
  1. 从 CGRAM 或 DDRAM 中读数据
  1. 指令码:

  1. 功能:从地址计数器 AC 指定的CGRAM 或者 DDRAM 单元中,读出数据 D7 ~ D0,在读数据之前,应先通过地址计数器 AC 正确指定读取单元的地址。
    1. LCD1602硬件电路设计

IK-64D4开发板上设计了LCD1602显示模块接口,电路如下图所示。这里需要注意的是第3引脚(VO)为显示屏对比度调整端口,电路中通过一个10K的电位器调整对比度,VO连接到电位器的抽头,通过旋转电位器旋钮即可改变电位器抽头电压,从而调整液晶屏对比度。

图7:LCD1602显示模块接口电路

LCD1602显示模块占用STC8A8K64D4的引脚如下表:

表2:LCD1602引脚分配

LCD1602引脚

信号名称

单片机

说明

1

VSS

连接到5V电源正

——

2

VDD

连接到5V电源负

——

3

VO

连接到电位器抽头

——

4

RS

P3.5

和LCD12864显示模块共用

5

RW

P3.4

和LCD12864显示模块共用

6

E

P3.2

和LCD12864显示模块共用

7

D0

P6.0

和LCD12864显示模块共用

8

D1

P6.1

和LCD12864显示模块共用

9

D2

P6.2

和LCD12864显示模块共用

10

D3

P6.3

和LCD12864显示模块共用

11

D4

P6.4

和LCD12864显示模块共用

12

D5

P6.5

和LCD12864显示模块共用

13

D6

P6.6

和LCD12864显示模块共用

14

D7

P6.7

和LCD12864显示模块共用

15

BLA

连接到5V电源正

——

16

BLK

连接到5V电源负

——

    1. 软件设计
      1. LCD1602显示字符实验
  • 注:本节的实验是在“实验2-6-1:串口1数据收发实验”的基础上修改,本节对应的实验源码是:“实验3-3-1:LCD1602显示字符”。
        1. 实验内容

LCD1602模式:8位数据总线(D0~D7);两行显示;5×7点阵显示模式。

上电启动后,LCD1602第一行显示“LCD1602 check ok”,第二行显示“0123456789ABCDEF”。之后,每秒修改一次第2行第10个字符显示区域的显示内容:循环显示数字0到9 。

        1. 代码编写
  1. 新建一个名称为“lcd1602.c”的文件及其头文件“lcd1602.h”并保存到工程的“Source”文件夹,并将“lcd1602.c”加入到Keil工程中的“SOURCE”组。
  2. 引用头文件

因为在“main.c”文件中使用了“lcd1602.c”文件中的函数,所以需要引用下面的头文件“lcd1602.h”。

代码清单:引用头文件

  1. //引用lcd1602的头文件  
  2. #include   "lcd1602.h"  
  1. 编写写指令和写数据的函数

根据前文描述的LCD1602显示模块的读写时序,编写的写命令函数和写数据函数代码清单如下。

代码清单:写命令

  1. /************************************************************************************** 
  2.  * 描  述 : LCD1602写命令函数 
  3.  * 参  数 : dat[in]:8位的命令数据 
  4.  * 返回值 : 无 
  5.  **************************************************************************************/  
  6. void LCD1602_WriteCmd(u8 com)                   
  7. {   
  8.    RS=0;               //选择指令寄存器   
  9.    RW=0;               //选择写操作  
  10.    P6=com;             //把命令送入到LCD1602屏8位数据口  
  11.    delay_ms(1);        //延时,LCD1602准备接收数据  
  12.    //控制LCD1602使能引脚产生高电平到低电平的跳变,液晶模块执行命令  
  13.    EN=1;               //使能引脚置高电平  
  14.    EN=0;               //使能引脚置低电平  
  15. }   

代码清单:写数据

  1. /************************************************************************************** 
  2.  * 描  述 : LCD1602写数据函数  
  3.  * 参  数 : dat[in]:8位的数据 
  4.  * 返回值 : 无 
  5.  **************************************************************************************/  
  6. void LCD1602_WriteData(u8 dat)            
  7. {   
  8.    RS=1;               //选择数据寄存器   
  9.    RW=0;               //选择写操作  
  10.    P6=dat;             //把命令送入到LCD1602屏8位数据口  
  11.    delay_ms(1);        //延时,LCD1602准备接收数据  
  12.    //控制LCD1602使能引脚产生高电平到低电平的跳变,液晶模块执行命令  
  13.    EN=1;               //使能引脚置高电平  
  14.    EN=0;               //使能引脚置低电平  
  15. }  

  1. LCD1602显示模块初始化

LCD1602显示模块使用前先要初始化,本例中配置LCD1602为8位数据总线(D0~D7)、两行显示、5×7点阵显示。配置后发送清屏指令清除LCD1602显示。

代码清单:LCD1602显示模块初始化

  1. /************************************************************************************** 
  2.  * 描  述 : LCD1602初始化 
  3.  * 参  数 : 无 
  4.  * 返回值 : 无 
  5.  **************************************************************************************/  
  6. void lcd1602_init(void)                   
  7. {   
  8.    LCD1602_WriteCmd(0x38);       //显示模式设置:16*2显示,5*7点阵,8位数据接口         
  9.    LCD1602_WriteCmd(0x0c);       //开显示,不显示光标,光标不闪烁   
  10.    LCD1602_WriteCmd(0x06);       //显示地址递增  
  11.    LCD1602_WriteCmd(0x01);       //清屏 
  12. }     

4. LCD1602在指定位置显示一个字符

LCD1602在指定位置显示字符时先写入DDRAM地址,然后再向该地址写入数据,即:先用“设置DDRAM地址指令”设置地址,然后用“向DDRAM或CGRAM写入数据指令”将待显示的字符编写写入该地址。

代码清单:在指定位置显示一个字符

  1. /************************************************************************************** 
  2.  * 描  述 : 在指定的字符显示区域显示一个字符 
  3.  * 参  数 : x[in]:行地址,范围是0~15,对应第1~第16个字符显示起始位置 
  4.  *        : y[in]:列地址,范围是0~1,对应第1、第2列 
  5.  *        : dat[in]:显示的数据 
  6.  * 返回值 : 无 
  7.  **************************************************************************************/  
  8. void LCD1602_DispOneChar(u8 x, u8 y, u8 dat)  
  9. {  
  10.    x &= 0x01;              //限制X不能大于1,Y不能大于15  
  11.    y &= 0x0F;  
  12.    if (x) y |= 0x40;       //当要显示第二行时地址码+0x40;  
  13.    y |= 0x80;              //写入地址时第7位必须为1  
  14.    LCD1602_WriteCmd(y);    //发命令字  
  15.    LCD1602_WriteData(dat); //发数据  
  16. }  

4. LCD1602在显示字符串

LCD1602显示字符串时,和显示单个字符一样,先写入DDRAM地址,然后再向该地址依次写入字符串中的字符。需要注意的是:字符串的长度不能超过LCD1602的字符显示区域能容纳的长度。

代码清单:在指定位置显示一个字符

  1. /************************************************************************************** 
  2.  * 描  述 : LCD1602从指定位置开始显示字符串,注意,字符串大小不能超过LCD1602显示区域 
  3.  * 参  数 : x[in]:行地址,范围是0~15,对应第1~第16个字符显示起始位置 
  4.  *        : y[in]:列地址,范围是0~1,对应第1、第2列 
  5.  *        : str[in]:显示的字符串,字符串以/0结尾 
  6.  * 返回值 : 无 
  7.  **************************************************************************************/  
  8. void LCD1602_DispString(u8 x, u8 y, u8 code *str)  
  9. {  
  10.    x &= 0x01; //限制X不能大于1,Y不能大于15  
  11.    y &= 0x0F;  
  12.       
  13.    if (x) y |= 0x40;   //当要显示第二行时地址码+0x40;  
  14.    y |= 0x80;          //写入地址时第7位必须为1  
  15.    LCD1602_WriteCmd(y);//DDRAM地址  
  16.    while(*str != '\0')  
  17.    {  
  18.       LCD1602_WriteData(*str);  
  19.       str++;  
  20.    }     
  1. 主函数

定义两个字符串,每个字符串包含16个字符,

分别存放将在LCD1602的两行上显示。注意,这里字符串数组用了“code”关键字修饰,因此,他们会被存放到代码区(Flash),他们是不能修改的,如果需要在程序中修改,删除“code”关键字即可。

代码清单:定义字符串数组

  1. u8 code table1[]="LCD1602 check ok";       //要显示的内容1放入数组table1  
  2. u8 code table2[]="0123456789ABCDEF";       //要显示的内容2放入数组table2  

主函数中,在进入主循环之前,在LCD1602第一行显示字符串数组“table1”中的内容“LCD1602 check ok”,第二行显示字符串数组“table2”中的内容“0123456789ABCDEF”。进入主循环后,每秒修改一次第2行第10个字符显示区域的显示内容:循环显示数字0到9 。

代码清单:主函数

  1. /********************************************************************************** 
  2. 功能描述:主函数 
  3. 参    数:无 
  4. 返 回 值:int类型 
  5. ***********************************************************************************/  
  6. int main(void)  
  7. {  
  8.    u8 i = 0;  
  9.    P2M1 &= 0xBF;   P2M0 &= 0xBF;     //设置P2.6为准双向口(指示灯D1)  
  10.    P3M1 &= 0xCB;   P3M0 |= 0x34;     //设置P3.2,P3.4,P3.5为强推挽输出(LCD1602控制)  
  11.    P6M1 &= 0x00;   P6M0 &= 0x00;     //设置P6.0~P6.7为准双向口(LCD1602数据)  
  12.    lcd1602_init();                   //LCD1602显示模块初始化   
  13.    LCD1602_DispString(0, 0, table1);   //第1行显示table1数组中的内容  
  14.    LCD1602_DispString(1, 0, table2);   //第2行显示table1数组中的内容  
  15.    while(1)  
  16.    {  
  17.       LCD1602_DispOneChar(1, 9, i+48);  //加48是为了将数字转转成对应的ASCII码  
  18.       i++;  
  19.       if(i==10) i = 0;  
  20.       delay_ms(500);                    //延时,方便观察数据  
  21.       led_toggle(LED_1);                //指示灯D1状态翻转,指示程序的运行  
  22.    }  
  23. }  
        1. 硬件连接

如下图所示,将LCD1602显示模块安装到J17端子上。

图8:硬件连接

        1. 实验步骤
  1. 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验3-3-1:LCD1602显示字符”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
  2. 双击“…\lcd1602\project”目录下的工程文件“lcd1602.uvproj”。
  3. 点击编译按钮编译工程,编译成功后生成的HEX文件“lcd1602.hex”位于工程的“…\lcd1602\Project\Object”目录下。
  4. 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
  5. 电脑上打开串口调试助手,选择开发板对应的串口号,将波特率设置为9600bps。
  6. 程序运行后,可以观察到LCD1602第一行显示“LCD1602 check ok”,第二行显示“0123456789ABCDEF”,之后,第2行第10个字符显示区域的显示内容以1秒的间隔循环显示数字0到9 。
      1. LCD1602滚动显示实验
  • 注:本节的实验是在“实验3-3-1:LCD1602显示字符”的基础上修改,本节对应的实验源码是:“实验3-3-2:LCD1602滚动显示”。
        1. 实验内容

让“实验3-3-1:LCD1602显示字符”中显示的内容以向左滚动的方式显示。

        1. 代码编写

LCD1602滚动显示很简单,只需要发送“光标或显示移位指令”这一条指令即可实现滚动,该指令每发送一次,移位一个字符显示区域。

这里需要注意一下:DDRAM实际大小是每行40个字节,其中前16个字节是和LCD1602的显示对应的,而滚动显示是按照DDRAM内容首尾衔接滚动的,所以在实验时会看到,滚动显示时中间有一部分是空的。如果要消除这部分空白,将DDRAM中第17到第40个地址都写入数据即可。

代码清单:LCD1602滚动显示

  1. /********************************************************************************** 
  2. 功能描述:主函数 
  3. 参    数:无 
  4. 返 回 值:int类型 
  5. ***********************************************************************************/  
  6. int main(void)  
  7. {  
  8.    //省略了无关的内容  
  9.       
  10.    while(1)  
  11.    {  
  12.       LCD1602_WriteCmd(0x18);    //光标和显示一起向左移动,该指令发送一次,移位一个字符显示区域  
  13.       delay_ms(600);             //延时600ms 
  14.       led_toggle(LED_1);         //指示灯D1状态翻转,指示程序的运行  
  15.     }  
  16. }  
        1. 硬件连接

同实验3-3-1.

        1. 实验步骤
  1. 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验3-3-2:LCD1602滚动显示”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
  2. 双击“…\lcd1602_scroll\project”目录下的工程文件“lcd1602_scroll.uvproj”。
  3. 点击编译按钮编译工程,编译成功后生成的HEX文件“lcd1602_scroll.hex”位于工程的“…\lcd1602_scroll\Project\Object”目录下。
  4. 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
  5. 电脑上打开串口调试助手,选择开发板对应的串口号,将波特率设置为9600bps。
  6. 程序运行后,可以观察到LCD1602以600ms的间隔向左滚动显示。
      1. LCD1602显示ADC采样电压实验
  • 注:本节的实验是在“实验3-3-1:LCD1602显示字符”的基础上修改,本节对应的实验源码是:“实验3-3-3:LCD1602显示ADC采样电压值”。
        1. 实验内容

使用ADC模拟通道输入14(即引脚P0.6)采样电位器抽头电压,程序中每1秒执行一次电压采样,采样结果计算为电压值后在LCD1602显示模块上显示。

  • 关于ADC应用相关的内容,读者可以参阅《第2-11讲:模数转换ADC》,本节我们关注的是LCD1602如何实时显示ADC采样的电压值。
        1. 代码编写

首先,定义一个大小为5个字节的用于存放显示内容的数组,由于数组中部分内容在显示电压的时候是无需改变的,因此,我们在定义的时候对数组进行初始化,这样,更新显示的时候,只需和电压相关的值就可以了。

代码清单:定义存放显示内容的数组

  1. //该字符串在程序运行过程中无需改变,所以用code关键字修饰  
  2. u8 code table1[]="Voltage:";   
  3. //因为ADC采样的电压不会超过2.5V,所以电压的整数部分1位,小数部分2位即可,再加上小数点和字母'V',一共5个字节  
  4. u8 Disp_Buff[5] = {0,'.',0,0,'V'};      

主函数中,先执行相关的初始化,在进入主循环之前,在LCD1602先显示出程序运行中无需更改的部分。进入主循环后,每秒采样一次电位器抽头的电压,并将电压在LCD1602上显示出来,显示的时候保留2位有效数字。

代码清单:主函数

  1. /********************************************************************************** 
  2. 功能描述:主函数 
  3. 参    数:无  
  4. 返 回 值:int类型 
  5. ***********************************************************************************/  
  6. int main(void)  
  7. {  
  8.    float adc_value;                  //存放ADC计算后的电压值  
  9.    int adc_int,tmp;  
  10.       
  11.    P2M1 &= 0xBF;   P2M0 &= 0xBF;     //设置P2.6为准双向口(指示灯D1)  
  12.    P3M1 &= 0xFE;   P3M0 &= 0xFE;     //设置P3.0为准双向口(串口1的RxD)  
  13.    P3M1 &= 0xFD;   P3M0 |= 0x02;     //设置P3.1为推挽输出(串口1的TxD)  
  14.    P3M1 &= 0xCB;   P3M0 |= 0x34;     //设置P3.2,P3.4,P3.5为强推挽输出(LCD1602控制)  
  15.    P6M1 &= 0x00;   P6M0 &= 0x00;     //设置P6.0~P6.7为准双向口(LCD1602数据)  
  16.    uart1_init();                     //串口1初始化  
  17.    lcd1602_init();               //LCD1602显示模块初始化   
  18.    adc_config();                 //初始化ADC  
  19.    EA = 1;                       //使能总中断  
  20.       
  21.    LCD1602_DispString(0, 0, table1);   //LCD1602显示无需改变的内容
  22.    LCD1602_DispOneChar(0,10,Disp_Buff[1]); //显示小数点
  23.    LCD1602_DispOneChar(0,13,Disp_Buff[4]); //显示字母‘V’
  24.    while(1)  
  25.    {  
  26.       adc_start();                               //启动ADC转换  
  27.       while(adc_completed() == false);           //等待ADC转换完成  
  28.       adc_value = (2.5*get_adc_value())/4096;    //读取ADC才采样值并转换为电压(单位V)  
  29.       printf("voltage: %.2fV\r\n",adc_value);   //串口打印ADC采样电压  
  30.       adc_int = (int)adc_value;                  //取整数部分  
  31.       Disp_Buff[0] = adc_int % 10 + 48;          //整数转换为ASCII码  
  32.       tmp = (int)((adc_value-adc_int)*100+0.5);  //保留2位小数,所以这里乘以100,加0.5是四舍五入
  33.       Disp_Buff[2] = tmp / 10 + 48;              //第1位小数转换为ASCII码  
  34.       Disp_Buff[3] = tmp % 10 + 48;              //第2位小数转换为ASCII码  
  35.       //LCD显示计算后的电压值  
  36.        LCD1602_DispOneChar(0,9,Disp_Buff[0]);  
  37.        LCD1602_DispOneChar(0,11,Disp_Buff[2]);  
  38.        LCD1602_DispOneChar(0,12,Disp_Buff[3]);  
  39.   
  40.        delay_ms(1000);                    //延时,方便观察数据  
  41.        led_toggle(LED_1);                 //指示灯D1状态翻转,指示程序的运行  
  42.    }  
  43. }
        1. 硬件连接
  1. 安装LCD1602显示模块。
  2. 按照下图短接ADC的跳线帽。

图9:ADC跳线帽短接

        1. 实验步骤
  1. 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验3-3-3:LCD1602显示ADC采样电压值”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
  2. 双击“…\lcd1602_adc\project”目录下的工程文件“lcd1602_adc.uvproj”。
  3. 点击编译按钮编译工程,编译成功后生成的HEX文件“lcd1602_adc.hex”位于工程的“…\lcd1602_adc\Project\Object”目录下。
  4. 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
  5. 电脑上打开串口调试助手,选择开发板对应的串口号,将波特率设置为9600bps。
  6. 程序运行后,可以观察到LCD1602实时显示ADC测量的电位器抽头的电压,旋转电位器改变电位器抽头电压,可以观察到LCD1602上显示的电压随之改变。
;