| Arduino我已经接触一段时间了,由于工作原因,不能天天玩这个,所以只能隔三岔五的搞点实验,现在把一些心得给大家分享一下。
今天玩的是字符液晶1602,有玩过1602字符液晶的朋友都知道,这个液晶分4总线和8总线2种驱动方式(关于该液晶的详细资料,大家可以自己搜索,这里就不做详细说明了)。我们用单片机驱动1602液晶,使用并口操作很容易就驱动起来了,但使用 Arduino板驱动1602液晶,还真有点费劲,因为他只能位操作。根据官方网站提供的例程,很容易看出他们使用的是最常用的8总线驱动方式,然而他巧妙的使用for循环语句完成了位操作的赋值。我们来看看官方的工程代码:
int DI = 12; int RW = 11; int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};//使用数组来定义总线需要的管脚 int Enable = 2;
void LcdCommandWrite(int value) { // poll all the pins int i = 0; for (i=DB[0]; i <= DI; i++) //总线赋值 { digitalWrite(i,value & 01); value >>= 1; } digitalWrite(Enable,LOW); delayMicroseconds(1); // send a pulse to enable digitalWrite(Enable,HIGH); delayMicroseconds(1); // pause 1 ms according to datasheet digitalWrite(Enable,LOW); delayMicroseconds(1); // pause 1 ms according to datasheet }
void LcdDataWrite(int value) { // poll all the pins int i = 0; digitalWrite(DI, HIGH); digitalWrite(RW, LOW); for (i=DB[0]; i <= DB[7]; i++) { digitalWrite(i,value & 01); value >>= 1; } digitalWrite(Enable,LOW); delayMicroseconds(1); // send a pulse to enable digitalWrite(Enable,HIGH); delayMicroseconds(1); digitalWrite(Enable,LOW); delayMicroseconds(1); // pause 1 ms according to datasheet }
void setup (void) { int i = 0; for (i=Enable; i <= DI; i++) { pinMode(i,OUTPUT); } delay(100); // initiatize lcd after a short pause // needed by the LCDs controller LcdCommandWrite(0x30); // set: // 8-bit interface, 1 display lines, 5x7 font delay(64); LcdCommandWrite(0x30); // set: // 8-bit interface, 1 display lines, 5x7 font delay(50); LcdCommandWrite(0x30); // set: // 8-bit interface, 1 display lines, 5x7 font delay(20); LcdCommandWrite(0x06); // entry mode set: // increment automatically, no display shift delay(20); LcdCommandWrite(0x0E); // display control: // turn display on, cursor on, no blinking delay(20); LcdCommandWrite(0x01); // clear display, set cursor position to zero delay(100); LcdCommandWrite(0x80); // display control: // turn display on, cursor on, no blinking delay(20); }
void loop (void) { LcdCommandWrite(0x02); // set cursor position to zero delay(10); // Write the welcome message LcdDataWrite('H'); LcdDataWrite('o'); LcdDataWrite('l'); LcdDataWrite('a'); LcdDataWrite(' '); LcdDataWrite('C'); LcdDataWrite('a'); LcdDataWrite('r'); LcdDataWrite('a'); LcdDataWrite('c'); LcdDataWrite('o'); LcdDataWrite('l'); LcdDataWrite('a'); delay(500); }
实验器材:Arduino DM 一个,USB电缆一根,LCD1602一个,单芯杜邦线若干。
根据例程定义接线图如下:

大家需要注意的是,液晶根据不同的颜色不同的型号,对比度(VEE)调节电压也不同,一般都需要接个电位器进行调节,本人使用的是灰膜液晶,VEE直接接到地即可。

例程编译后,下载进Arduino,显示居然不正常,如图:

一般这种液晶上电或没有正常初始化就会出现一排黑块,但我仔细检查了程序和电路连线,也没有看出什么问题,难道液晶坏了?我又把液晶拆到我的51实验板上验证是好的,我开始怀疑是对比度调节的问题,于是把液晶拿起来一看,果然是对比度不对。
斜着看,就能看见“Hola Caracila”的字样,也就是我们实验需要显示的内容。这款灰膜液晶我使用很多次,对比度调节端都是直接接地,没有任何问题,怎么用这个程序就出现这样的问题,于是我又找到官方网站仔细探头究竟,终于被我发现问题的所在,官方网站使用的是2001的液晶(好象是这个型号),是单排显示的一排显示20个字符, 因此这个问题就出在液晶的功能初始化设置上了,我开始没有注意,所以就直接套用程序了。
根据我们使用的液晶更改功能初始化设置,指令集如下表:


根据指令6,将官方提供的代码初始化部分:
LcdCommandWrite(0x30); // set: // 8-bit interface, 1 display lines, 5x7 font delay(64); LcdCommandWrite(0x30); // set: // 8-bit interface, 1 display lines, 5x7 font delay(50); LcdCommandWrite(0x30); // set: // 8-bit interface, 1 display lines, 5x7 font
更改为8总线、双行显示、5x7:
LcdCommandWrite(0x38); // set: // 8-bit interface, 2 display lines, 5x7 font delay(64); LcdCommandWrite(0x38); // set: // 8-bit interface, 2 display lines, 5x7 font delay(50); LcdCommandWrite(0x38); // set: // 8-bit interface, 2 display lines, 5x7 font
更改后编译、下载,显示结果如下:

是不是能够很清楚的看见“Hola Caracila”的字样了。
Arduino DM的数字端口只有14个,那么LCD1602就占用了10个,浪费了不少资源,对我们以后的电路扩展带来了极大的不便。于是我就可以使用该液晶的4总线驱动方式,可以节省3个数字端口出来作其他扩展。本人编写的工程代码如下:
/********************************************************************/ int LCD1602_RS=12;
int LCD1602_RW=11;
int LCD1602_EN=10;
int DB[] = { 6, 7, 8, 9};
char str1[]="Welcome to";
char str2[]="www.DFRobot.cn"; /********************************************************************/
/********************************************************************/ void LCD_Command_Write(int command) { int i,temp; digitalWrite( LCD1602_RS,LOW); digitalWrite( LCD1602_RW,LOW); digitalWrite( LCD1602_EN,LOW);
temp=command & 0xf0; for (i=DB[0]; i <= 9; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; } digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW);
temp=(command & 0x0f)<<4; for (i=DB[0]; i <= 10; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; }
digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW); }
/********************************************************************/ void LCD_Data_Write(int dat) { int i=0,temp; digitalWrite( LCD1602_RS,HIGH); digitalWrite( LCD1602_RW,LOW); digitalWrite( LCD1602_EN,LOW);
temp=dat & 0xf0; for (i=DB[0]; i <= 9; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; }
digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW);
temp=(dat & 0x0f)<<4; for (i=DB[0]; i <= 10; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; }
digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW); }
/********************************************************************/ void LCD_SET_XY( int x, int y ) { int address; if (y ==0) address = 0x80 + x; else address = 0xC0 + x; LCD_Command_Write(address); }
/********************************************************************/ void LCD_Write_Char( int x,int y,int dat) { LCD_SET_XY( x, y ); LCD_Data_Write(dat); }
/********************************************************************/ void LCD_Write_String(int X,int Y,char *s) { LCD_SET_XY( X, Y ); //设置地址 while (*s) //写字符串 { LCD_Data_Write(*s); s ++; } }
/********************************************************************/ void setup (void) { int i = 0; for (i=6; i <= 12; i++) { pinMode(i,OUTPUT); } delay(100); LCD_Command_Write(0x28);//4线 2行 5x7 delay(50); LCD_Command_Write(0x06); delay(50); LCD_Command_Write(0x0c); delay(50); LCD_Command_Write(0x80); delay(50); LCD_Command_Write(0x01); delay(50);
}
/********************************************************************/ void loop (void) { LCD_Command_Write(0x02); delay(50); LCD_Write_String(3,0,str1);//第1行,第4个地址起 delay(50); LCD_Write_String(1,1,str2);//第2行,第2个地址起 while(1); } 根据程序定义接线图如下:


编译后,下载进Arduino,显示如图:

这个代码容易移植,以后需要用到显示的地方,都可以直接引用。
找到了Arduino语言关于字符液晶4总线的库函数,使用该库函数程序就变的相当简洁了。函数例程如下:
#i nclude <LCD4Bit.h> LCD4Bit lcd = LCD4Bit(1); //传递参数1和2,表示选择1线和2线字符液晶。 lcd.clear();//清屏 delay(1000);//延时 lcd.printIn("arduino");//显示字符串 lcd.cursorTo(2, 0); //line=2, x=0 lcd.leftScroll(20, 50);//將LCD上现有的文字以50ms的速度向左移动20个字符位
注意:若使用LCD4Bit.h的话,RW需要接地.
下载“LCD4Bit.h”
|