2008年10月29日 星期三

Arduino 連接 LCD1602

Arduino&LCD1602 

wxxmickey 发表于 - 2008-5-9 21:34:00

      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”

沒有留言: