Arduino LCD1602驱动

一、前言:

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

  LCD1602,也叫1602液晶,是一种专门用来显示字母、数字、符号等的点阵型液晶模块,工业字符型液晶的一种,能够同时显示16x02即32个字符。主控芯片是HD44780或者其它兼容芯片,而市面上字符液晶大多数是基于HD44780液晶芯片的。

 

二、LCD的技术资料

<1>.基本参数:

 

显示容量:16×2个字符

芯片工作电压:4.5—5.5V

工作电流:2.0mA(5.0V)

模块最佳工作电压:5.0V

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

 

 

 引脚说明:

第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的指令说明及时序

lcd1602操作时序图:


lcd1602操作写时序图

  1、当我们要写指令字,设置lcd1602的工作方式时:需要把RS置为低电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。

  2、当我们要写入数据字,在lcd1602上实现显示时:需要把RS置为高电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。


lcd1602操作读时序图

  如何看懂lcd1602时序图:

  1、注意时序图时间轴,如果没有标明(其实大部分时序图也都是不标明的),那么从左往右的方向为时间正向轴,即时间在增长。

  2、看懂时序图所需的一些常识:

  (1)时序图最左边一般是某一根引脚的标识,表示此行图线体现该引脚的变化。

  (2)时序图有线交叉状的部分,表示电平在变化。

  (3)两条平行线分别对应高低电平,也正好吻合(2)中电平变化的说法。

  (4)图中下部密封的菱形部分,注意要密封,表示数据有效,Valid Data这个词也显示了这点。

  3、看时序图需要十分严重注意的是,时序图里各个引脚的电平变化,基于时序图的时间轴是一致的。一定要严格按照时序图时间轴的增长方向来精确地观察时序图。要让器件严格的遵守时序图的变化。在类似于18B20这样的单总线器件对此要求尤为严格。

  4、以上几点,并不是lcd1602的时序图所特有的,绝大部分的时序图都遵循着这样的一般规则,所以我们应该习惯于这样的规则。

  也许你还注意到了上面的时序图有许多关于时间的标注,这也是个十分重要的信息,这些时间的标注表明了某些状态所要维持的最短或最长时间。因为器件的工作速度也是有限的,一般都跟不上主控芯片的速度,所以它们直接之间要有时序配合。

<3>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) 短延时

三、Arduino 不用库驱动

<1>LCD1602数据八线驱动

/*Arduino在8位接法下不使用LiquidCrystal库
* 输出欢迎界面和Hello World!
* 作者:Tony Yang 
* 2020/1/12
*/

int RS = 12;                             //数据/命令选择器引脚(RS)
int RW = 11;                            //读/写选择器引脚(R/W)
int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};    //使用数组来定义总线需要的管脚(D0-D7)
int Enable = 2;                            //使能(E)

void LcdCommandWrite(int value) {
    // 定义所有引脚
    int i = 0;
    digitalWrite(RS, LOW);
    digitalWrite(RW, LOW);
    for (i=DB[0]; i <=DB[7]; i++) //总线赋值
    {
        //这里的&是二进制的“与”运算。取指令码的最低位。
       digitalWrite(i,value & 0x01);
       value >>= 1;
    }
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);        // 延时1us
    digitalWrite(Enable,HIGH);
    delayMicroseconds(1);          // 延时1us
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);          // 延时1us
}

void LcdDataWrite(int value) {
    // 定义所有引脚
    int i = 0;
    digitalWrite(RS, HIGH);
    digitalWrite(RW, LOW);
    for (i=DB[0]; i <= DB[7]; i++) {
       digitalWrite(i,value & 0x01);
       value >>= 1;
    }
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);        // 延时1us
    digitalWrite(Enable,HIGH);
    delayMicroseconds(1);        // 延时1us
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);          // 延时1us
}

void setup (void) {
    int i = 0;
    for (i=Enable; i <= RS; i++) {
       pinMode(i,OUTPUT);
    }
    delay(100);
    // 短暂的停顿后初始化LCD
    // 用于LCD控制需要
    LcdCommandWrite(0x38);         // 设置为8-bit接口,2行显示,5x7文字大小
    delay(20);
    LcdCommandWrite(0x06);        // 输入方式设定,自动增量,画面没有移位
    delay(20);
    LcdCommandWrite(0x0C);        // 显示设置,开启显示屏,光标关,无闪烁
    delay(20);
}

void loop (void) {
  LcdCommandWrite(0x01);           // 屏幕清空,光标位置归零
  delay(10);
  LcdCommandWrite(0x80+5);         // 定义光标位置为第一行第五个位置
  delay(10);
  // 写入欢迎信息
  LcdDataWrite('W');
  LcdDataWrite('e');
  LcdDataWrite('l');
  LcdDataWrite('c');
  LcdDataWrite('o');
  LcdDataWrite('m');
  LcdDataWrite('e');
  delay(10);
  LcdCommandWrite(0xc0+2);          // 定义光标位置为第二行第二个位置
  delay(10);
  LcdDataWrite('I');
  LcdDataWrite(' ');
  LcdDataWrite('a');
  LcdDataWrite('m');
  LcdDataWrite(' ');
  LcdDataWrite('T');
  LcdDataWrite('o');
  LcdDataWrite('n');
  LcdDataWrite('y');
  LcdDataWrite('Y');
  LcdDataWrite('o');
  LcdDataWrite('n');
  LcdDataWrite('y');
  delay(3000);
  LcdCommandWrite(0x01);            // 屏幕清空,光标位置归零
  delay(10);
  LcdCommandWrite(0x80+2);          //定义光标位置为第一行第二个位置
  delay(10);
  LcdDataWrite('H');
  LcdDataWrite('e');
  LcdDataWrite('l');
  LcdDataWrite('l');
  LcdDataWrite('o');
  LcdDataWrite(' ');
  LcdDataWrite('W');
  LcdDataWrite('o');
  LcdDataWrite('r');
  LcdDataWrite('l');
  LcdDataWrite('d');
  LcdDataWrite('!');
  delay(5000);
}

  

<1>LCD1602数据四线驱动

/*Arduino在4位接法下不使用LiquidCrystal库
* 输出欢迎界面和Hello World!
* 作者:Tony Yang
* 2020/1/12
*/

int RS = 14;                             //数据/命令选择器引脚(RS)
int RW = 15;                            //读/写选择器引脚(R/W)
int DB[] = {7, 8, 9, 10};                //使用数组来定义总线需要的管脚(D7-D4)
int Enable = 16;                        //使能(E)

void LcdCommandWrite(int value) {
    // 定义所有引脚
    int i = 0;
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);        // 延时1us
    digitalWrite(RS, LOW);
    digitalWrite(RW, LOW);

    /* 7      8       9     10
    *  D7     D6      D5    D4
    *  DB[0] DB[1] DB[2] DB[3]
    */
    int temp=value & 0xf0;//取指令高4位
    for (i=DB[0]; i <= 10; i++)
    {
        if((temp & 0x80)!=0)//取指令最高位
            digitalWrite(i,HIGH);
        else
            digitalWrite(i,LOW );
        temp <<= 1;
    }
    delayMicroseconds(1);        // 延时1us
    digitalWrite(Enable,HIGH);
    delayMicroseconds(1);          // 延时1us
    digitalWrite(Enable,LOW);

    temp=(value & 0x0f)<<4;
    for (i=DB[0]; i <= 10; i++)
    {
        if((temp & 0x80)!=0)//取指令最高位
            digitalWrite(i,HIGH);
        else
            digitalWrite(i,LOW );
        temp <<= 1;
    }
    delayMicroseconds(1);          // 延时1us
    digitalWrite(Enable,HIGH);
    delayMicroseconds(1);          // 延时1us
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);          // 延时1us
}

void LcdDataWrite(int value) {
    // 定义所有引脚
    int i = 0;
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);        // 延时1us
    digitalWrite(RS, HIGH);
    digitalWrite(RW, LOW);
    int temp=value& 0xf0;
    for (i=DB[0]; i <= 10; i++)
    {
        if((temp & 0x80)!=0)//取指令最高位
            digitalWrite(i,HIGH);
        else
            digitalWrite(i,LOW );
        temp <<= 1;
    }
    digitalWrite(Enable,HIGH);
    delayMicroseconds(1);        // 延时1us
    digitalWrite(Enable,LOW);

    temp=(value & 0x0f)<<4;
    for (i=DB[0]; i <= 10; i++)
    {
        if((temp & 0x80)!=0)//取指令最高位
            digitalWrite(i,HIGH);
        else
            digitalWrite(i,LOW );
        temp <<= 1;
    }
    delayMicroseconds(1);        // 延时1us
    digitalWrite(Enable,HIGH);
    delayMicroseconds(1);        // 延时1us
    digitalWrite(Enable,LOW);
    delayMicroseconds(1);          // 延时1us
}

void setup (void) {
   // int i = 0;
   //for (i=Enable; i <= RS; i++) {
   // pinMode(i,OUTPUT);
   //}

   pinMode(14,OUTPUT);
   pinMode(15,OUTPUT);
   pinMode(16,OUTPUT);
   pinMode(8,OUTPUT);
   pinMode(9,OUTPUT);
   pinMode(10,OUTPUT);
   pinMode(7,OUTPUT);
  
   
    delay(100);
    // 短暂的停顿后初始化LCD
    // 用于LCD控制需要
    LcdCommandWrite(0x38);         // 设置为8-bit接口,2行显示,5x7文字大小
    delay(20);
    LcdCommandWrite(0x06);      // 输入方式设定,自动增量,画面没有移位
    delay(20);
    LcdCommandWrite(0x0C);      // 显示设置,开启显示屏,光标关,无闪烁
    delay(20);
}

void loop (void) {
  LcdCommandWrite(0x01);          // 屏幕清空,光标位置归零
  delay(10);
  LcdCommandWrite(0x80+5);         // 定义光标位置为第一行第五个位置
  delay(10);
  // 写入欢迎信息
  LcdDataWrite('W');
  LcdDataWrite('e');
  LcdDataWrite('l');
  LcdDataWrite('c');
  LcdDataWrite('o');
  LcdDataWrite('m');
  LcdDataWrite('e');
  delay(10);
  LcdCommandWrite(0xc0+2);          // 定义光标位置为第二行第二个位置
  delay(10);
  LcdDataWrite('I');
  LcdDataWrite(' ');
  LcdDataWrite('a');
  LcdDataWrite('m');
  LcdDataWrite(' ');
  LcdDataWrite('T');
  LcdDataWrite('o');
  LcdDataWrite('n');
  LcdDataWrite('y');
  LcdDataWrite('Y');
  LcdDataWrite('a');
  LcdDataWrite('n');
  LcdDataWrite('y');
  delay(3000);
  LcdCommandWrite(0x01);         // 屏幕清空,光标位置归零
  delay(10);
  LcdCommandWrite(0x80+2);         //定义光标位置为第一行第二个位置
  delay(10);
  LcdDataWrite('H');
  LcdDataWrite('e');
  LcdDataWrite('l');
  LcdDataWrite('l');
  LcdDataWrite('o');
  LcdDataWrite(' ');
  LcdDataWrite('W');
  LcdDataWrite('o');
  LcdDataWrite('r');
  LcdDataWrite('l');
  LcdDataWrite('d');
  LcdDataWrite('!');
  LcdCommandWrite(0xc0);          // 定义光标位置为第二行起始位置
  delay(10);
  LcdDataWrite('4');
  LcdDataWrite('-');
  LcdDataWrite('B');
  LcdDataWrite('i');
  LcdDataWrite('t');
  LcdDataWrite('-');
  LcdDataWrite('I');
  LcdDataWrite('n');
  LcdDataWrite('t');
  LcdDataWrite('e');
  LcdDataWrite('r');
  LcdDataWrite('f');
  LcdDataWrite('a');
  LcdDataWrite('c');
  LcdDataWrite('e');
  delay(10);
  delay(5000);
}

  

四、Arduino 库驱动

<1>LCD1602数据八线驱动

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

  

  

<1>LCD1602数据四线驱动

* 作者:Tony Yang
* 2022/1/12
* R/W接地
*const int rs = 14, en = 15, d4 = 4, d5 = 3, d6 = 6, d7 = 7; //Mention the pin number for LCD connection
*LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
*/
#include<LiquidCrystal.h>
LiquidCrystal  lcd(14,15,16,4,3,6,7);    //初始化LCD,

void setup(){
    lcd.begin(16,2);                               //设置LCD为16列*2行
}
void loop(){
    lcd.clear();                                //清屏操作
    lcd.setCursor(5,0);                            //设置光标位置为第一行,第六列
    lcd.print("Welcome");                        //在LCD上输出信息
    delay(10);                                    //延时程序
    lcd.setCursor(2,1);
    lcd.print("I am Tony Yang");
    delay(3000);
    lcd.clear();
    lcd.setCursor(2,0);
    lcd.print("Hello World!");
    lcd.setCursor(0,1);
    lcd.print("4-Bit-Interface");
    delay(5000);
}

  

posted @ 2022-01-12 13:41  xiaoberber  阅读(695)  评论(0编辑  收藏  举报