• Arduino下LCD1602综合探究(上)——1602的两种驱动方式,如何使LCD的控制编程变得更简单


    本文为大大维原创,最早于博客园发表,转载请注明出处!!!

     

    一、前言:

      LCD ( Liquid Crystal Display 的简称)液晶显示器,已经逐渐替代CRT成为主流的显示设备之一,因此也成为了单片机发烧友绕不过的话题之一;而LCD1602更是很多单片机发烧友最早接触的字符型液晶显示器。笔者经过一段时间的深入学习,对其驱动有了些许心得,特地记录于此,以备以后查阅。

      LCD1602,也叫1602液晶,是一种专门用来显示字母、数字、符号等的点阵型液晶模块,工业字符型液晶的一种,能够同时显示16x02即32个字符。主控芯片是HD44780或者其它兼容芯片,而市面上字符液晶大多数是基于HD44780液晶芯片的,控制原理是完全相同的。因此尽管LCD1602可显示的内容十分有限,但在此花点时间是完全值得的。

    二、LCD的一些背景知识:

    <1>LCD1602基本参数及引脚功能:

    1.LCD1602的分类:

      LCD1602分为带背光和不带背光两种,带背光的比不带背光的厚,是否带背光在应用中并无差别,两者尺寸差别如下图10-54所示:

    在本文中,笔者选用的是带背光的一种。

      

    2.基本参数:

    显示容量:16×2个字符

    芯片工作电压:4.5—5.5V

    工作电流:2.0mA(5.0V)

    模块最佳工作电压:5.0V

    字符尺寸:2.95×4.35(W×H)mm

    2.引脚功能说明

      1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下:

    编号

    符号

    引脚说明

    编号

    符号

    引脚说明

    1

    VSS

    电源地

    9

    D2

    数据

    2

    VDD

    电源正极

    10

    D3

    数据

    3

    VL

    液晶显示偏压

    11

    D4

    数据

    4

    RS

    数据/命令选择

    12

    D5

    数据

    5

    R/W

    读/写选择

    13

    D6

    数据

    6

    E

    使能信号

    14

    D7

    数据

    7

    D0

    数据

    15

    BLA

    背光源正极

    8

    D1

    数据

    16

    BLK

    背光源负极

     

    各引脚说明:

    第1脚:VSS为地电源。

    第2脚:VDD接5V正电源。

    第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

    第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

    第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。

    第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

    第7~14脚:D0~D7为8位双向数据线。

    第15脚:背光源正极。

    第16脚:背光源负极

    <2>LCD1602的指令说明及时序

    1.与HD44780相兼容的芯片时序表如下:

    读状态

    输入

    RS=L,R/W=H,E=H

    输出

    D0—D7=状态字

    写指令

    输入

    RS=L,R/W=L,D0—D7=指令码,E=高脉冲

    输出

    读数据

    输入

    RS=H,R/W=H,E=H

    输出

    D0—D7=数据

    写数据

    输入

    RS=H,R/W=L,D0—D7=数据,E=高脉冲

    输出

    2.LCD1602的指令说明:

      1602液晶模块内部的控制器共有11条控制指令,如表所示:

    序号

    指令

    RS

    R/W

    D7

    D6

    D5

    D4

    D3

    D2

    D1

    D0

    1

    清显示

    0

    0

    0

    0

    0

    0

    0

    0

    0

    1

    2

    光标返回

    0

    0

    0

    0

    0

    0

    0

    0

    1

    *

    3

    置输入模式

    0

    0

    0

    0

    0

    0

    0

    1

    I/D

    S

    4

    显示开/关控制

    0

    0

    0

    0

    0

    0

    1

    D

    C

    B

    5

    光标或字符移位

    0

    0

    0

    0

    0

    1

    S/C

    R/L

    *

    *

    6

    置功能

    0

    0

    0

    0

    1

    DL

    N

    F

    *

    *

    7

    置字符发生存贮器地址

    0

    0

    0

    1

    字符发生存贮器地址

    8

    置数据存贮器地址

    0

    0

    1

    显示数据存贮器地址

    9

    读忙标志或地址

    0

    1

    BF

    计数器地址

    10

    写数到CGRAM或DDRAM

    1

    0

    要写的数据内容

    11

    从CGRAM或DDRAM读数

    1

    1

    读出的数据内容

    者在百度文库中发现一个特别好的介绍1602指令集的文章,给大家分享如下:

    点击查看

    <3>LCD1602的RAM地址映射及标准字库表

    1.LCD1602的RAM地址映射

      液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,下图是1602的内部显示地址:

    在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。

    2.LCD1602的标准字库表

      1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如下图所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等。

    在使用标准字库中的字符图形时,无需自己制作字模即可直接使用,若要显示汉字等标准字库中没有的元素,则需要自己在DDRAM中制作字模。

    <4>LCD1602四线驱动的约定流程

    1、  写入指令:

    1) EN = 0 (LCD使能禁止)

    2) 短延时

    3) RS = 0  ,RW = 0  (准备写入指令)

    4) DATA = 指令的高4位(ATA代表D7、D6、D5、D4,下同)

    5) 短延时

    6) EN = 1 (LCD使能允许,指令写入)

    7) 短延时

    8) EN = 0 (LCD使能禁止)

    9) DATA = 指令的低4位 

    10) 短延时

    11) EN = 1 (LCD使能允许,指令写入)

    12) 短延时

    13) EN = 0 (LCD使能禁止)

    14) 短延时

    2、  写入数据:

    1) EN = 0 (LCD使能禁止)

    2) 短延时

    3) RS = 1 ,RW = 0 (准备写入数据)

    4) DATA = 数据的高4位

    5) 短延时

    6) EN = 1 (LCD使能允许,数据写入)

    7) 短延时

    8) EN = 0 (LCD使能禁止)

    9) DATA = 数据的低4位

    10) 短延时

    11) EN = 1 (LCD使能允许,数据写入)

    12) 短延时

    13) EN = 0 (LCD使能禁止)

    14) 短延时

    三、关于LCD控制库LiquidCrystal:

      LiquidCrystal是Arduino的官方库之一,他可以控制基于日立公司HD44780(或兼容)芯片集成的字符型LCD。该库可以通过四线或者八线模式控制LCD。

    无疑,LiquidCrystal库可以使LCD的控制编程变得十分简单!!!

    笔者在学习中,发现了一个比较完整的LiquidCrystal库的中文资料,链接如下:

    点击查看

    下面,就一些常用的LiquidCrystal库函数做一个简单介绍:

    1.LiquidCrystal()构造函数

    2.begin()指定显示方式

    3.clear()清屏,光标置于左上角

    4.home()接下来的字符从左上角显示

    5.setCursor(col,row)设置光标位置

    6.print()LCD显示字符

    四、Arduino下的LCD1602的8线驱动模式:

    <1>优缺点

     八线模式的优点是每位数据均从单独的数据线传输,因此数据传输速度快。但缺点也是显然的,需要占掉大量的端口。

    <2>接线方式

    VL为液晶显示器对比度调整端,有条件的话,最好使用一个10K的电位器来调整对比度。限于条件,笔者通过反复调试,最后选择了4k电阻,效果也还可以。

    <3>试验代码

    1.不使用LiquidCrystal库

      1 /*Arduino在8位接法下不使用LiquidCrystal库
      2 * 输出欢迎界面和Hello World!
      3 * 作者:大大维
      4 * 2016/10/23
      5 */
      6 
      7 int RS = 12;                             //数据/命令选择器引脚(RS)    
      8 int RW = 11;                            //读/写选择器引脚(R/W)
      9 int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};    //使用数组来定义总线需要的管脚(D0-D7)
     10 int Enable = 2;                            //使能(E)    
     11 
     12 void LcdCommandWrite(int value) {
     13     // 定义所有引脚
     14     int i = 0;
     15     digitalWrite(RS, LOW);
     16     digitalWrite(RW, LOW);
     17     for (i=DB[0]; i <= RS; i++) //总线赋值
     18     {
     19         //这里的&是二进制的“与”运算。取指令码的最低位。
     20        digitalWrite(i,value & 0x01);
     21        value >>= 1;
     22     }
     23     digitalWrite(Enable,LOW);
     24     delayMicroseconds(1);        // 延时1us
     25     digitalWrite(Enable,HIGH);
     26     delayMicroseconds(1);          // 延时1us
     27     digitalWrite(Enable,LOW);
     28     delayMicroseconds(1);          // 延时1us
     29 }
     30 
     31 void LcdDataWrite(int value) {
     32     // 定义所有引脚
     33     int i = 0;
     34     digitalWrite(RS, HIGH);
     35     digitalWrite(RW, LOW);
     36     for (i=DB[0]; i <= DB[7]; i++) {
     37        digitalWrite(i,value & 0x01);
     38        value >>= 1;
     39     }
     40     digitalWrite(Enable,LOW);
     41     delayMicroseconds(1);        // 延时1us
     42     digitalWrite(Enable,HIGH);
     43     delayMicroseconds(1);        // 延时1us
     44     digitalWrite(Enable,LOW);
     45     delayMicroseconds(1);          // 延时1us
     46 }
     47 
     48 void setup (void) {
     49     int i = 0;
     50     for (i=Enable; i <= RS; i++) {
     51        pinMode(i,OUTPUT);   
     52     }
     53     delay(100);
     54     // 短暂的停顿后初始化LCD
     55     // 用于LCD控制需要
     56     LcdCommandWrite(0x38);         // 设置为8-bit接口,2行显示,5x7文字大小                     
     57     delay(20);                      
     58     LcdCommandWrite(0x06);        // 输入方式设定,自动增量,画面没有移位
     59     delay(20);                      
     60     LcdCommandWrite(0x0C);        // 显示设置,开启显示屏,光标关,无闪烁
     61     delay(20);                                  
     62 }
     63 
     64 void loop (void) {
     65   LcdCommandWrite(0x01);           // 屏幕清空,光标位置归零  
     66   delay(10); 
     67   LcdCommandWrite(0x80+5);         // 定义光标位置为第一行第五个位置
     68   delay(10);                     
     69   // 写入欢迎信息 
     70   LcdDataWrite('W');
     71   LcdDataWrite('e');
     72   LcdDataWrite('l');
     73   LcdDataWrite('c');
     74   LcdDataWrite('o');
     75   LcdDataWrite('m');
     76   LcdDataWrite('e');
     77   delay(10);
     78   LcdCommandWrite(0xc0+2);          // 定义光标位置为第二行第二个位置  
     79   delay(10); 
     80   LcdDataWrite('I');
     81   LcdDataWrite(' ');
     82   LcdDataWrite('a');
     83   LcdDataWrite('m');
     84   LcdDataWrite(' ');
     85   LcdDataWrite('D');
     86   LcdDataWrite('a');
     87   LcdDataWrite('D');
     88   LcdDataWrite('a');
     89   LcdDataWrite('W');
     90   LcdDataWrite('e');
     91   LcdDataWrite('i');
     92   delay(3000);
     93   LcdCommandWrite(0x01);            // 屏幕清空,光标位置归零
     94   delay(10);
     95   LcdCommandWrite(0x80+2);          //定义光标位置为第一行第二个位置
     96   delay(10);  
     97   LcdDataWrite('H');
     98   LcdDataWrite('e');
     99   LcdDataWrite('l');
    100   LcdDataWrite('l');
    101   LcdDataWrite('o');
    102   LcdDataWrite(' ');
    103   LcdDataWrite('W');
    104   LcdDataWrite('o');
    105   LcdDataWrite('r');
    106   LcdDataWrite('l');
    107   LcdDataWrite('d');
    108   LcdDataWrite('!');
    109   delay(5000);
    110 }

     看到上面的代码,是否觉得略显复杂?但要是使用了LiquidCrystal库,一切将变得十分简单!!!

    2.使用LiquidCrystal库

     1 /*Arduino在8位接法下使用LiquidCrystal库
     2 * 输出欢迎界面和Hello World!
     3 * 作者:大大维
     4 * 2016/10/23
     5 */
     6 #include<LiquidCrystal.h>
     7 LiquidCrystal lcd(12,11,3,4,5,6,7,8,9,10);           //初始化LCD
     8 void setup(){
     9     lcd.begin(16,2);                                 //设置LCD为16列*2行
    10 }
    11 void loop(){
    12     lcd.clear();                                    //清屏操作
    13     lcd.setCursor(5,0);                              //设置光标位置为第一行,第六列
    14     lcd.print("Welcome");                           //在LCD上输出信息
    15     delay(10);                                       //延时程序
    16     lcd.setCursor(2,1);
    17     lcd.print("I am DaDaWei");
    18     delay(3000);
    19     lcd.clear();
    20     lcd.setCursor(2,0);
    21     lcd.print("Hello World!");
    22     delay(5000);
    23 }

    <4>试验展示

    演示视频

    五、Arduino下的LCD1602的四线驱动模式:

    <1>优缺点

     四线模式相对于八线模式的优点是占用的端口更少,减少了四条数据线,也就是说八位的数据需要通过四条线来发送,那么会导致四线模式比八线模式数据速度慢些。

    <2>接线方式

    <3>试验代码

     1.不使用LiquidCrystal库

      1 /*Arduino在4位接法下不使用LiquidCrystal库
      2 * 输出欢迎界面和Hello World!
      3 * 作者:大大维
      4 * 2016/10/23
      5 */
      6 
      7 int RS = 12;                             //数据/命令选择器引脚(RS)    
      8 int RW = 11;                            //读/写选择器引脚(R/W)
      9 int DB[] = {6, 7, 8, 9};                //使用数组来定义总线需要的管脚(D0-D7)
     10 int Enable = 10;                        //使能(E)    
     11 
     12 void LcdCommandWrite(int value) {
     13     // 定义所有引脚
     14     int i = 0;
     15     digitalWrite(Enable,LOW);
     16     delayMicroseconds(1);        // 延时1us
     17     digitalWrite(RS, LOW);
     18     digitalWrite(RW, LOW);
     19     
     20     /* 6     7     8     9
     21     *  D7     D6      D5    D4 
     22     *  DB[0] DB[1] DB[2] DB[3]
     23     */
     24     int temp=value & 0xf0;//取指令高4位
     25     for (i=DB[0]; i <= 9; i++)
     26     {
     27         if((temp & 0x80)!=0)//取指令最高位
     28             digitalWrite(i,HIGH);
     29         else
     30             digitalWrite(i,LOW );    
     31         temp <<= 1;
     32     }
     33     delayMicroseconds(1);        // 延时1us
     34     digitalWrite(Enable,HIGH);
     35     delayMicroseconds(1);          // 延时1us
     36     digitalWrite(Enable,LOW);
     37     
     38     temp=(value & 0x0f)<<4;
     39     for (i=DB[0]; i <= 9; i++)
     40     {
     41         if((temp & 0x80)!=0)//取指令最高位
     42             digitalWrite(i,HIGH);
     43         else
     44             digitalWrite(i,LOW );    
     45         temp <<= 1;
     46     }    
     47     delayMicroseconds(1);          // 延时1us
     48     digitalWrite(Enable,HIGH);
     49     delayMicroseconds(1);          // 延时1us
     50     digitalWrite(Enable,LOW);
     51     delayMicroseconds(1);          // 延时1us
     52 }
     53 
     54 void LcdDataWrite(int value) {
     55     // 定义所有引脚
     56     int i = 0;
     57     digitalWrite(Enable,LOW);
     58     delayMicroseconds(1);        // 延时1us
     59     digitalWrite(RS, HIGH);
     60     digitalWrite(RW, LOW);
     61     int temp=value& 0xf0;
     62     for (i=DB[0]; i <= 9; i++)
     63     {
     64         if((temp & 0x80)!=0)//取指令最高位
     65             digitalWrite(i,HIGH);
     66         else
     67             digitalWrite(i,LOW );    
     68         temp <<= 1;
     69     }
     70     digitalWrite(Enable,HIGH);
     71     delayMicroseconds(1);        // 延时1us
     72     digitalWrite(Enable,LOW);
     73 
     74     temp=(value & 0x0f)<<4;
     75     for (i=DB[0]; i <= 9; i++)
     76     {
     77         if((temp & 0x80)!=0)//取指令最高位
     78             digitalWrite(i,HIGH);
     79         else
     80             digitalWrite(i,LOW );    
     81         temp <<= 1;
     82     }
     83     delayMicroseconds(1);        // 延时1us
     84     digitalWrite(Enable,HIGH);
     85     delayMicroseconds(1);        // 延时1us
     86     digitalWrite(Enable,LOW);
     87     delayMicroseconds(1);          // 延时1us
     88 }
     89 
     90 void setup (void) {
     91     int i = 0;
     92     for (i=Enable; i <= RS; i++) {
     93        pinMode(i,OUTPUT);   
     94     }
     95     delay(100);
     96     // 短暂的停顿后初始化LCD
     97     // 用于LCD控制需要
     98     LcdCommandWrite(0x38);         // 设置为8-bit接口,2行显示,5x7文字大小                     
     99     delay(20);                      
    100     LcdCommandWrite(0x06);      // 输入方式设定,自动增量,画面没有移位
    101     delay(20);                      
    102     LcdCommandWrite(0x0C);      // 显示设置,开启显示屏,光标关,无闪烁
    103     delay(20);                                  
    104 }
    105 
    106 void loop (void) {
    107   LcdCommandWrite(0x01);          // 屏幕清空,光标位置归零  
    108   delay(10); 
    109   LcdCommandWrite(0x80+5);         // 定义光标位置为第一行第五个位置
    110   delay(10);                     
    111   // 写入欢迎信息 
    112   LcdDataWrite('W');
    113   LcdDataWrite('e');
    114   LcdDataWrite('l');
    115   LcdDataWrite('c');
    116   LcdDataWrite('o');
    117   LcdDataWrite('m');
    118   LcdDataWrite('e');
    119   delay(10);
    120   LcdCommandWrite(0xc0+2);          // 定义光标位置为第二行第二个位置  
    121   delay(10); 
    122   LcdDataWrite('I');
    123   LcdDataWrite(' ');
    124   LcdDataWrite('a');
    125   LcdDataWrite('m');
    126   LcdDataWrite(' ');
    127   LcdDataWrite('D');
    128   LcdDataWrite('a');
    129   LcdDataWrite('D');
    130   LcdDataWrite('a');
    131   LcdDataWrite('W');
    132   LcdDataWrite('e');
    133   LcdDataWrite('i');
    134   delay(3000);
    135   LcdCommandWrite(0x01);         // 屏幕清空,光标位置归零
    136   delay(10);
    137   LcdCommandWrite(0x80+2);         //定义光标位置为第一行第二个位置
    138   delay(10);  
    139   LcdDataWrite('H');
    140   LcdDataWrite('e');
    141   LcdDataWrite('l');
    142   LcdDataWrite('l');
    143   LcdDataWrite('o');
    144   LcdDataWrite(' ');
    145   LcdDataWrite('W');
    146   LcdDataWrite('o');
    147   LcdDataWrite('r');
    148   LcdDataWrite('l');
    149   LcdDataWrite('d');
    150   LcdDataWrite('!');
    151   LcdCommandWrite(0xc0);          // 定义光标位置为第二行起始位置  
    152   delay(10);
    153   LcdDataWrite('4');
    154   LcdDataWrite('-');
    155   LcdDataWrite('B');
    156   LcdDataWrite('i');
    157   LcdDataWrite('t');
    158   LcdDataWrite('-');
    159   LcdDataWrite('I');
    160   LcdDataWrite('n');
    161   LcdDataWrite('t');
    162   LcdDataWrite('e');
    163   LcdDataWrite('r');
    164   LcdDataWrite('f');
    165   LcdDataWrite('a');
    166   LcdDataWrite('c');
    167   LcdDataWrite('e');
    168   delay(10); 
    169   delay(5000);
    170 }

    2.使用LiquidCrystal库

     1 /*Arduino在4位接法下使用LiquidCrystal库
     2 * 输出欢迎界面和Hello World!
     3 * 作者:大大维
     4 * 2016/10/23
     5 */
     6 #include<LiquidCrystal.h>
     7 LiquidCrystal lcd(13,12,11,10,9,8,7);            //初始化LCD
     8 void setup(){
     9     lcd.begin(16,2);                               //设置LCD为16列*2行
    10 }
    11 void loop(){
    12     lcd.clear();                                //清屏操作
    13     lcd.setCursor(5,0);                            //设置光标位置为第一行,第六列
    14     lcd.print("Welcome");                        //在LCD上输出信息
    15     delay(10);                                    //延时程序
    16     lcd.setCursor(2,1);
    17     lcd.print("I am DaDaWei");
    18     delay(3000);
    19     lcd.clear();
    20     lcd.setCursor(2,0);
    21     lcd.print("Hello World!");
    22     lcd.setCursor(0,1);
    23     lcd.print("4-Bit-Interface");
    24     delay(5000);
    25 }

    <4>试验展示

     演示视频

  • 相关阅读:
    IOS异常日志记录与展现功能
    关于仿网易新闻中详细页图文混排功能的实现
    IOS开发基础知识--碎片22
    利用UIScrollView实现几个页面的切换
    IOS开发基础知识--碎片21
    IOS开发基础知识--碎片20
    左右侧滑菜单功能的实现
    空页面的背景提示原理
    等待时动画效果的实现
    解析虚拟VMware三种网络模式的根本区别
  • 原文地址:https://www.cnblogs.com/liujw2114/p/6011214.html
Copyright © 2020-2023  润新知