弘毅 发表于 2011-7-20 16:07:57

arduino学习笔记10 - 1602液晶实验

本帖最后由 弘毅 于 2013-5-19 17:53 编辑

本次试验使用arduino直接驱动1602液晶显示文字

1602液晶在应用中非常广泛,最初的1602液晶使用的是HD44780控制器,现在各个厂家的1602模块基本上都是采用了与之兼容的IC,所以特性上基本都是一致的。

1602LCD主要技术参数
显示容量为16×2个字符;
芯片工作电压为4.5~5.5V;
工作电流为2.0mA(5.0V);
模块最佳工作电压为5.0V;
字符尺寸为2.95×4.35(W×H)mm。

1602液晶接口引脚定义



接口说明:
1、两组电源 一组是模块的电源 一组是背光板的电源 一般均使用5V供电。本次试验背光使用3.3V供电也可以工作。
2、VL是调节对比度的引脚,串联不大于5KΩ的电位器进行调节。本次实验使用1KΩ的电阻来设定对比度。其连接分高电位与低电位接法,本次使用低电位接法,串联1KΩ电阻后接GND。
注意:不同液晶的对比度电阻是不同的,最好是接一个电位器进行测试,本次实验使用的1KΩ电阻在其他液晶上不一定正确。
3、RS 是很多液晶上都有的引脚 是命令/数据选择引脚 该脚电平为高时表示将进行数据操作;为低时表示进行命令操作。
4、RW 也是很多液晶上都有的引脚 是读写选择端 该脚电平为高是表示要对液晶进行读操作;为低时表示要进行写操作。
5、E 同样很多液晶模块有此引脚 通常在总线上信号稳定后给一正脉冲通知把数据读走,在此脚为高电平的时候总线不允许变化。
6、D0—D7 8 位双向并行总线,用来传送命令和数据。
7、BLA是背光源正极,BLK是背光源负极。

1602液晶的基本操作分以下四种:



下图就是1602液晶实物图





1602直接与arduino通信,根据产品手册描述,分8位连接法与4位连接法,咱们先使用8位连接法进行实验。硬件连接方式如下图





代码如下int DI = 12;
int RW = 11;
int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};//使用数组来定义总线需要的管脚
int Enable = 2;

void LcdCommandWrite(int value) {
// 定义所有引脚
int i = 0;
for (i=DB; i <= DI; i++) //总线赋值
{
   digitalWrite(i,value & 01);//因为1602液晶信号识别是D7-D0(不是D0-D7),这里是用来反转信号。
   value >>= 1;
}
digitalWrite(Enable,LOW);
delayMicroseconds(1);
digitalWrite(Enable,HIGH);
delayMicroseconds(1);// 延时1ms
digitalWrite(Enable,LOW);
delayMicroseconds(1);// 延时1ms
}

void LcdDataWrite(int value) {
// 定义所有引脚
int i = 0;
digitalWrite(DI, HIGH);
digitalWrite(RW, LOW);
for (i=DB; i <= DB; i++) {
   digitalWrite(i,value & 01);
   value >>= 1;
}
digitalWrite(Enable,LOW);
delayMicroseconds(1);
digitalWrite(Enable,HIGH);
delayMicroseconds(1);
digitalWrite(Enable,LOW);
delayMicroseconds(1);// 延时1ms
}

void setup (void) {
int i = 0;
for (i=Enable; i <= DI; i++) {
   pinMode(i,OUTPUT);
}
delay(100);
// 短暂的停顿后初始化LCD
// 用于LCD控制需要
LcdCommandWrite(0x38);// 设置为8-bit接口,2行显示,5x7文字大小                     
delay(64);                     
LcdCommandWrite(0x38);// 设置为8-bit接口,2行显示,5x7文字大小                        
delay(50);                     
LcdCommandWrite(0x38);// 设置为8-bit接口,2行显示,5x7文字大小                        
delay(20);                     
LcdCommandWrite(0x06);// 输入方式设定
                         // 自动增量,没有显示移位
delay(20);                     
LcdCommandWrite(0x0E);// 显示设置
                         // 开启显示屏,光标显示,无闪烁
delay(20);                     
LcdCommandWrite(0x01);// 屏幕清空,光标位置归零
delay(100);                     
LcdCommandWrite(0x80);// 显示设置
                         // 开启显示屏,光标显示,无闪烁
delay(20);                     
}

void loop (void) {
LcdCommandWrite(0x01);// 屏幕清空,光标位置归零
delay(10);
LcdCommandWrite(0x80+3);
delay(10);                     
// 写入欢迎信息
LcdDataWrite('W');
LcdDataWrite('e');
LcdDataWrite('l');
LcdDataWrite('c');
LcdDataWrite('o');
LcdDataWrite('m');
LcdDataWrite('e');
LcdDataWrite(' ');
LcdDataWrite('t');
LcdDataWrite('o');
delay(10);
LcdCommandWrite(0xc0+1);// 定义光标位置为第二行第二个位置
delay(10);
LcdDataWrite('g');
LcdDataWrite('e');
LcdDataWrite('e');
LcdDataWrite('k');
LcdDataWrite('-');
LcdDataWrite('w');
LcdDataWrite('o');
LcdDataWrite('r');
LcdDataWrite('k');
LcdDataWrite('s');
LcdDataWrite('h');
LcdDataWrite('o');
LcdDataWrite('p');
delay(5000);
LcdCommandWrite(0x01);// 屏幕清空,光标位置归零
delay(10);
LcdDataWrite('I');
LcdDataWrite(' ');
LcdDataWrite('a');
LcdDataWrite('m');
LcdDataWrite(' ');
LcdDataWrite('h');
LcdDataWrite('o');
LcdDataWrite('n');
LcdDataWrite('g');
LcdDataWrite('y');
LcdDataWrite('i');
delay(3000);
LcdCommandWrite(0x02); //设置模式为新文字替换老文字,无新文字的地方显示不变。
delay(10);
LcdCommandWrite(0x80+5); //定义光标位置为第一行第六个位置
delay(10);
LcdDataWrite('t');
LcdDataWrite('h');
LcdDataWrite('e');
LcdDataWrite(' ');
LcdDataWrite('a');
LcdDataWrite('d');
LcdDataWrite('m');
LcdDataWrite('i');
LcdDataWrite('n');
delay(5000);
}实验效果如下
http://player.youku.com/player.php/sid/XMjg2NTkxODY0/v.swf

4位接法

在正常使用下,8位接法基本把arduino的数字端口占满了,如果想要多接几个传感器就没有端口了,这种情况下怎么处理呢,咱们可以使用4位接法。

4位接法的硬件连接方法如下图





硬件接好后把下面的代码上传到控制板上,看看效果。int LCD1602_RS=12;   
int LCD1602_RW=11;   
int LCD1602_EN=10;   
int DB[] = { 6, 7, 8, 9};
char str1[]="Welcome to";
char str2[]="geek-workshop";
char str3[]="this is the";
char str4[]="4-bit interface";

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; 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; i <= 9; 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; 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; i <= 9; 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(0x01);
   delay(50);
   LCD_Write_String(3,0,str1);//第1行,第4个地址起
   delay(50);
   LCD_Write_String(1,1,str2);//第2行,第2个地址起
   delay(5000);
   LCD_Command_Write(0x01);
   delay(50);
   LCD_Write_String(0,0,str3);
   delay(50);
   LCD_Write_String(0,1,str4);
   delay(5000);
   
}
4位接法实验效果如下

http://player.youku.com/player.php/sid/XMjg3MDE5MDIw/v.swf

这里我们讲解一下最关键的部分,就是LCD的控制命令。
在上面两段代码中,我们常常可以遇到0x01,0x38这种参数。这些参数代表什么呢?
在C/C++语言中,0x38代表的是十六进制的数值"38","0x"的意思就是十六进制。
先打开win7下的计算器,选择“程序员”“基本”,



然后咱们选择“十六进制”,输入“38”,



然后再点击“二进制”。这时十六进制的“38”就会转换为二进制下的数值“111000”。



以8位控制法接LCD是,对应的控制信息就是“00111000”



同理,也可以把二进制的控制信息,逆运算为十六进制的。

有的产品说明书写的控制命令是"38H"
这里说明一下,一般情况下
十六进制 前缀0x 后缀h
十进制 后缀D
八进制 后缀Q
二进制 后缀B
但是不同的程序语言,对于十六进制的表达方式不完全相同,在arduino下,表达十六进制数值“38”只能使用“0x38”而不能用“38H”

最后放三个附件,是三个不同厂家的1602 LCD手册,供大家深入研究。





━__Neo_ˇ 发表于 2011-7-21 18:56:55

不错 不错!````学习 学习···

mauree 发表于 2011-8-3 15:31:36

写得很详细啊,对新手很好。

shyjdn 发表于 2011-11-10 11:34:16

筆記詳細,也很直觀,對我們初學者真的很有幫助!

树·水·风 发表于 2011-12-22 11:53:57

我不明白,把data写进显存DDRAM和将显存中的data显示到屏幕上两者的关系,显存是40x2,屏幕是16x2,倘若我要显示DDRAM中第17列、第2行存放的data到屏幕上该怎么办?
另外LiquidCrystal库中lcd.print()和lcd.write()的区别是什么?
:)

aliao 发表于 2011-12-31 13:31:37

谢谢啦
我正不知道特此通知连接

弘毅 发表于 2011-12-31 21:36:10

树·水·风 发表于 2011-12-22 11:53 static/image/common/back.gif
我不明白,把data写进显存DDRAM和将显存中的data显示到屏幕上两者的关系,显存是40x2,屏幕是16x2,倘若我要 ...

=.=这些底层的东西,偶也云里雾里的,不太明白。。。。偶水平基本上就是能让他显示=.=

Lemonade 发表于 2012-1-9 02:04:53

microseconds 是微秒 缩写是us 不是ms

ardyPro 发表于 2012-2-20 19:14:43

树·水·风 发表于 2011-12-22 11:53 static/image/common/back.gif
我不明白,把data写进显存DDRAM和将显存中的data显示到屏幕上两者的关系,显存是40x2,屏幕是16x2,倘若我要 ...

显存中上下两列都只能使用前16个地址,1602没法使用后面的,所以你写入第17列的数据没法自动显示,除非你自己读出来,然后再放到前面的地址中去。

树·水·风 发表于 2012-2-20 22:51:22

ardyPro 发表于 2012-2-20 19:14 static/image/common/back.gif
显存中上下两列都只能使用前16个地址,1602没法使用后面的,所以你写入第17列的数据没法自动显示,除非你 ...

貌似懂了。以后再试试。
买的模块没有针脚,老是接触不良,悲催呀

xpaul 发表于 2012-4-28 22:52:30

1602A 的8位接法显示正常。
但4位接法是乱码:L。。。。。不知那里出问题了:(

弘毅 发表于 2012-4-29 09:29:04

xpaul 发表于 2012-4-28 22:52 static/image/common/back.gif
1602A 的8位接法显示正常。
但4位接法是乱码。。。。。不知那里出问题了

{:soso_e103:} 仔细检查检查线序

xpaul 发表于 2012-4-29 17:45:29

检查过线序,还是一样。:(

xpaul 发表于 2012-4-29 17:50:29

本帖最后由 xpaul 于 2012-4-29 17:51 编辑

但按官网的4位接法,正常。。。。:lol

xpaul 发表于 2012-4-29 17:52:35

:):):):):):)

/*
   LiquidCrystal Library - Hello World

Demonstrates the use a 16x2 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 "Hello World!" to the LCD
and shows the time.

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 resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)

Library originally added 18 Apr 2008
by David A. Mellis
library modified 5 Jul 2009
by Limor Fried (http://www.ladyada.net)
example added 9 Jul 2009
by Tom Igoe
modified 22 Nov 2010
by Tom Igoe

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/LiquidCrystal
*/

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("hello, world!");
}

void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print(millis()/1000);
}



只是要用到LiquidCrystal.h库文件,和R/W接地了,改变了2,3,4,5Pin脚输出。{:soso_e113:}
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: arduino学习笔记10 - 1602液晶实验