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的数字端口只有13个,那么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”
沒有留言:
張貼留言