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); }