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

一、前言:

  上文中,笔者系统的阐述了1602的两种驱动方式,并简单的提到了Arduino的LiquidCrystal库。本文紧接上文,对以下两个问题进行更加深入的探讨:如何能够使1602对Arduino的端口占用降到最少?LiquidCrystal库到底应该如何学习?闲话少说,下面开始进入正文。

二、减少1602对Arduino的端口占用

<1>不使用IC

  在上文中,笔者分别介绍八线和四线驱动的使用方法,给出了两种接线方式。接线图分别如下:

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

  在八线驱动模式下,总共占掉了Arduino 16个端口,四线驱动模式虽然比八线驱动模式少了四个端口,但也达到了惊人的12个。如果实验只是用于驱动LCD1602还好,但在其他实际应用中,这是不能容忍的。为此,怎么能够使端口占用达到最少呢?在上面两张接线图中,我们使用了两种电源,+5V的VSS和+3.3V背光。其实,背光完全可以接到+5V,而且亮度还会更高。此为,我们在实际使用操作过程中,RW一般均为低电平写。没有什么特殊需求的话可以直接接地。另外,我们如果养成良好的接线习惯,将GND接在一起,这样,只用占用一个GND端口。由于我们下文要用到Arduino中自带的示例程序,为了与示例程序的电路连接相符,对相关引脚连线做了一定调整,调整后的连线图如下:

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

  可以看到,这种接法下,Arduino端口的占用可以少去很多。尤其在四线驱动模式下,除去GND和+5V,LCD1602独占的端口只有6个。

<1>使用IC

  IC是由以前的PHILIPS(现在的NXP)公司开发的一种通信协议,其目的就是减少芯片之间的连线。在使用了IC之后,连接到Arduino上的线总共只有四条,独占的端口只有两个!!!

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

  但这种模式也有很多限制,罗列如下:

1.使用的LCD1602必须先焊接到LCD1602 IC模块

2.IC模块的SDA(串行数据)和SCL(串行时钟)不可以随便乱接。对于Arduino Uno来说,SDA必须接A4,SCL必须接A5

  尽管有这些限制,但无疑,它的确在很大程度上减少了芯片之间的连线。

  使用IC需要遵循IC协议。一般在Arduino中,通过导入LiquidCrystal_I2C库来完成控制。由于笔者手边没有LCD1602 IC模块,因此,相关实验在此略过,等有机会再进行补充。

三、LiquidCrystal库到底应该如何学习?

  在Arduino IDE中,官方的示例程序足够让你完成对LiquidCrystal的学习,如下图:(所有这些程序的硬件连接与上文的LCD1602四线驱动硬件连接简化示意图相同)

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

  此外,笔者分享一个不错的LiquidCrystal文档,可以当作LiquidCrystal说明手册使用。连接如下:

点击查看

  当然,你如果想深究,打开Arduino文件夹中的libraries文件夹,找到LiquidCrystal.cpp和头文件LiquidCrystal.h仔细研究(前提是你有良好的C++基础)。

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

四、LiquidCrystal库中的一个BUG以及相应的解决办法

  笔者在学习LiquidCrystal库的过程中,发现一处LiquidCrystal库中的bug,记录如下:

<1>BUG描述

  示例程序LiquidCrystal->CustomCharacter无论如何也编译不过去,即使硬件一点毛病也没有,编译也还是报错。如下图:

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

报错信息如下:

CustomCharacter.ino: In function 'void setup()':
CustomCharacter:: error: call of overloaded 'write(int)' is ambiguous
E:\Arduino\libraries\LiquidCrystal/LiquidCrystal.h:: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t)
E:\Arduino\hardware\arduino\cores\arduino/Print.h:: note: size_t Print::write(const char*)

error: call of overloaded 'write(int)' is ambiguous

翻译:write的重载是不明确的。//明显是由于参数判断不清楚导致的错误。
后面的意思是问题在LiquidCrystal::write(uint8_t)和size_t Print::write(const char*)两个方法之间。

原文代码如下:

 #include <LiquidCrystal.h>

 #include <LiquidCrystal.h>

 /*
LiquidCrystal Library - Custom Characters Demonstrates how to add custom characters on an LCD display.
The LiquidCrystal library works with all LCD displays that are
compatible with the Hitachi HD44780 driver. There are many of
them out there, and you can usually tell them by the 16-pin interface. This sketch prints "I <heart> Arduino!" and a little dancing man
to the LCD. The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* 10K potentiometer:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
* 10K poterntiometer on pin A0 created21 Mar 2011
by Tom Igoe
Based on Adafruit's example at
https://github.com/adafruit/SPI_VFD/blob/master/examples/createChar/createChar.pde This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/LiquidCrystal Also useful:
http://icontexto.com/charactercreator/ */ // include the library code:
#include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins
LiquidCrystal lcd(, , , , , ); // make some custom characters:
byte heart[] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000
}; byte smiley[] = {
0b00000,
0b00000,
0b01010,
0b00000,
0b00000,
0b10001,
0b01110,
0b00000
}; byte frownie[] = {
0b00000,
0b00000,
0b01010,
0b00000,
0b00000,
0b00000,
0b01110,
0b10001
}; byte armsDown[] = {
0b00100,
0b01010,
0b00100,
0b00100,
0b01110,
0b10101,
0b00100,
0b01010
}; byte armsUp[] = {
0b00100,
0b01010,
0b00100,
0b10101,
0b01110,
0b00100,
0b00100,
0b01010
};
void setup() {
// create a new character
lcd.createChar(0, heart);//方法2:0改为5
// create a new character
lcd.createChar(, smiley);
// create a new character
lcd.createChar(, frownie);
// create a new character
lcd.createChar(, armsDown);
// create a new character
lcd.createChar(, armsUp); // set up the lcd's number of columns and rows:
lcd.begin(, );
// Print a message to the lcd.
lcd.print("I ");
lcd.write(0);//方法一:改作lcd.write(0.0);
            //方法2: 0改为5
lcd.print(" Arduino! ");
lcd.write(); } void loop() {
// read the potentiometer on A0:
int sensorReading = analogRead(A0);
// map the result to 200 - 1000:
int delayTime = map(sensorReading, , , , );
// set the cursor to the bottom row, 5th position:
lcd.setCursor(, );
// draw the little man, arms down:
lcd.write();
delay(delayTime);
lcd.setCursor(, );
// draw him arms up:
lcd.write();
delay(delayTime);
}

笔者通过分析,和多处查阅资料。发现这是一个LiquidCrystal库中的bug。原因与LiquidCrystal.h中关于unit8_t的定义有关。

<2>BUG的解决办法

  目前为止,笔者通过自己研究和多方查找资料,发现了三种可行的办法,分别介绍如下:

  1.将示例程序中119行中的lcd.write(0)改作lcd.write(0.0),在上文的实验代码中用红字已经标注出。

  2.将示例程序中lcd.createChar()函数构造自定义字符时,编码从1开始,放弃0编码。即将105行和119行的0改作5。同样在上文的实验代码中用蓝字已经标注出。

  3.修改LiquidCrystal.h头文件。这种方法虽然比较麻烦,但修改彻底,一劳永逸!示例代码不用修改,实际应用也可直接从0开始编码,强烈推荐这种方法!!!修改方法如下:

  打开LiquidCrystal.h头文件,注释掉第85行的using Print::write。

如下图所示:(笔者用NotePad++打开):

Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法-LMLPHP

04-14 09:40