极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 356051|回复: 165

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

  [复制链接]
发表于 2011-7-20 16:07:57 | 显示全部楼层 |阅读模式
本帖最后由 弘毅 于 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位连接法进行实验。硬件连接方式如下图





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

  5. void LcdCommandWrite(int value) {
  6. // 定义所有引脚
  7. int i = 0;
  8. for (i=DB[0]; i <= DI; i++) //总线赋值
  9. {
  10.    digitalWrite(i,value & 01);//因为1602液晶信号识别是D7-D0(不是D0-D7),这里是用来反转信号。
  11.    value >>= 1;
  12. }
  13. digitalWrite(Enable,LOW);
  14. delayMicroseconds(1);
  15. digitalWrite(Enable,HIGH);
  16. delayMicroseconds(1);  // 延时1ms
  17. digitalWrite(Enable,LOW);
  18. delayMicroseconds(1);  // 延时1ms
  19. }

  20. void LcdDataWrite(int value) {
  21. // 定义所有引脚
  22. int i = 0;
  23. digitalWrite(DI, HIGH);
  24. digitalWrite(RW, LOW);
  25. for (i=DB[0]; i <= DB[7]; i++) {
  26.    digitalWrite(i,value & 01);
  27.    value >>= 1;
  28. }
  29. digitalWrite(Enable,LOW);
  30. delayMicroseconds(1);
  31. digitalWrite(Enable,HIGH);
  32. delayMicroseconds(1);
  33. digitalWrite(Enable,LOW);
  34. delayMicroseconds(1);  // 延时1ms
  35. }

  36. void setup (void) {
  37. int i = 0;
  38. for (i=Enable; i <= DI; i++) {
  39.    pinMode(i,OUTPUT);
  40. }
  41. delay(100);
  42. // 短暂的停顿后初始化LCD
  43. // 用于LCD控制需要
  44. LcdCommandWrite(0x38);  // 设置为8-bit接口,2行显示,5x7文字大小                     
  45. delay(64);                     
  46. LcdCommandWrite(0x38);  // 设置为8-bit接口,2行显示,5x7文字大小                        
  47. delay(50);                     
  48. LcdCommandWrite(0x38);  // 设置为8-bit接口,2行显示,5x7文字大小                        
  49. delay(20);                     
  50. LcdCommandWrite(0x06);  // 输入方式设定
  51.                          // 自动增量,没有显示移位
  52. delay(20);                     
  53. LcdCommandWrite(0x0E);  // 显示设置
  54.                          // 开启显示屏,光标显示,无闪烁
  55. delay(20);                     
  56. LcdCommandWrite(0x01);  // 屏幕清空,光标位置归零  
  57. delay(100);                     
  58. LcdCommandWrite(0x80);  // 显示设置
  59.                          // 开启显示屏,光标显示,无闪烁
  60. delay(20);                     
  61. }

  62. void loop (void) {
  63.   LcdCommandWrite(0x01);  // 屏幕清空,光标位置归零  
  64.   delay(10);
  65.   LcdCommandWrite(0x80+3);
  66.   delay(10);                     
  67.   // 写入欢迎信息
  68.   LcdDataWrite('W');
  69.   LcdDataWrite('e');
  70.   LcdDataWrite('l');
  71.   LcdDataWrite('c');
  72.   LcdDataWrite('o');
  73.   LcdDataWrite('m');
  74.   LcdDataWrite('e');
  75.   LcdDataWrite(' ');
  76.   LcdDataWrite('t');
  77.   LcdDataWrite('o');
  78.   delay(10);
  79.   LcdCommandWrite(0xc0+1);  // 定义光标位置为第二行第二个位置  
  80.   delay(10);
  81.   LcdDataWrite('g');
  82.   LcdDataWrite('e');
  83.   LcdDataWrite('e');
  84.   LcdDataWrite('k');
  85.   LcdDataWrite('-');
  86.   LcdDataWrite('w');
  87.   LcdDataWrite('o');
  88.   LcdDataWrite('r');
  89.   LcdDataWrite('k');
  90.   LcdDataWrite('s');
  91.   LcdDataWrite('h');
  92.   LcdDataWrite('o');
  93.   LcdDataWrite('p');
  94.   delay(5000);
  95.   LcdCommandWrite(0x01);  // 屏幕清空,光标位置归零  
  96.   delay(10);
  97.   LcdDataWrite('I');
  98.   LcdDataWrite(' ');
  99.   LcdDataWrite('a');
  100.   LcdDataWrite('m');
  101.   LcdDataWrite(' ');
  102.   LcdDataWrite('h');
  103.   LcdDataWrite('o');
  104.   LcdDataWrite('n');
  105.   LcdDataWrite('g');
  106.   LcdDataWrite('y');
  107.   LcdDataWrite('i');
  108.   delay(3000);
  109.   LcdCommandWrite(0x02); //设置模式为新文字替换老文字,无新文字的地方显示不变。
  110.   delay(10);
  111.   LcdCommandWrite(0x80+5); //定义光标位置为第一行第六个位置
  112.   delay(10);  
  113.   LcdDataWrite('t');
  114.   LcdDataWrite('h');
  115.   LcdDataWrite('e');
  116.   LcdDataWrite(' ');
  117.   LcdDataWrite('a');
  118.   LcdDataWrite('d');
  119.   LcdDataWrite('m');
  120.   LcdDataWrite('i');
  121.   LcdDataWrite('n');
  122.   delay(5000);
  123. }
复制代码
实验效果如下


4位接法

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

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






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

  9. void LCD_Command_Write(int command)
  10. {
  11. int i,temp;
  12. digitalWrite( LCD1602_RS,LOW);
  13. digitalWrite( LCD1602_RW,LOW);
  14. digitalWrite( LCD1602_EN,LOW);

  15. temp=command & 0xf0;
  16. for (i=DB[0]; i <= 9; i++)
  17. {
  18.    digitalWrite(i,temp & 0x80);
  19.    temp <<= 1;
  20. }

  21. digitalWrite( LCD1602_EN,HIGH);
  22. delayMicroseconds(1);
  23. digitalWrite( LCD1602_EN,LOW);

  24. temp=(command & 0x0f)<<4;
  25. for (i=DB[0]; i <= 9; i++)
  26. {
  27.    digitalWrite(i,temp & 0x80);
  28.    temp <<= 1;
  29. }

  30. digitalWrite( LCD1602_EN,HIGH);
  31. delayMicroseconds(1);
  32. digitalWrite( LCD1602_EN,LOW);
  33. }

  34. void LCD_Data_Write(int dat)
  35. {
  36. int i=0,temp;
  37. digitalWrite( LCD1602_RS,HIGH);
  38. digitalWrite( LCD1602_RW,LOW);
  39. digitalWrite( LCD1602_EN,LOW);

  40. temp=dat & 0xf0;
  41. for (i=DB[0]; i <= 9; i++)
  42. {
  43.    digitalWrite(i,temp & 0x80);
  44.    temp <<= 1;
  45. }

  46. digitalWrite( LCD1602_EN,HIGH);
  47. delayMicroseconds(1);
  48. digitalWrite( LCD1602_EN,LOW);

  49. temp=(dat & 0x0f)<<4;
  50. for (i=DB[0]; i <= 9; i++)
  51. {
  52.    digitalWrite(i,temp & 0x80);
  53.    temp <<= 1;
  54. }

  55. digitalWrite( LCD1602_EN,HIGH);
  56. delayMicroseconds(1);
  57. digitalWrite( LCD1602_EN,LOW);
  58. }

  59. void LCD_SET_XY( int x, int y )
  60. {
  61.   int address;
  62.   if (y ==0)    address = 0x80 + x;
  63.   else          address = 0xC0 + x;
  64.   LCD_Command_Write(address);
  65. }

  66. void LCD_Write_Char( int x,int y,int dat)
  67. {
  68.   LCD_SET_XY( x, y );
  69.   LCD_Data_Write(dat);
  70. }

  71. void LCD_Write_String(int X,int Y,char *s)
  72. {
  73.     LCD_SET_XY( X, Y );    //设置地址
  74.     while (*s)             //写字符串
  75.     {
  76.       LCD_Data_Write(*s);   
  77.       s ++;
  78.     }
  79. }

  80. void setup (void)
  81. {
  82.   int i = 0;
  83.   for (i=6; i <= 12; i++)
  84.    {
  85.      pinMode(i,OUTPUT);
  86.    }
  87.   delay(100);
  88.   LCD_Command_Write(0x28);//4线 2行 5x7
  89.   delay(50);
  90.   LCD_Command_Write(0x06);
  91.   delay(50);
  92.   LCD_Command_Write(0x0c);
  93.   delay(50);
  94.   LCD_Command_Write(0x80);
  95.   delay(50);
  96.   LCD_Command_Write(0x01);
  97.   delay(50);

  98. }

  99. void loop (void)
  100. {
  101.    LCD_Command_Write(0x01);
  102.    delay(50);
  103.    LCD_Write_String(3,0,str1);//第1行,第4个地址起
  104.    delay(50);
  105.    LCD_Write_String(1,1,str2);//第2行,第2个地址起
  106.    delay(5000);
  107.    LCD_Command_Write(0x01);
  108.    delay(50);
  109.    LCD_Write_String(0,0,str3);
  110.    delay(50);
  111.    LCD_Write_String(0,1,str4);
  112.    delay(5000);
  113.    
  114. }
复制代码

4位接法实验效果如下




这里我们讲解一下最关键的部分,就是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手册,供大家深入研究。





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2011-7-21 18:56:55 | 显示全部楼层
不错 不错!````学习 学习···
回复 支持 反对

使用道具 举报

发表于 2011-8-3 15:31:36 | 显示全部楼层
写得很详细啊,对新手很好。
回复 支持 反对

使用道具 举报

发表于 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()的区别是什么?
回复 支持 反对

使用道具 举报

发表于 2011-12-31 13:31:37 | 显示全部楼层
谢谢啦
我正不知道特此通知连接
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-12-31 21:36:10 | 显示全部楼层
树·水·风 发表于 2011-12-22 11:53
我不明白,把data写进显存DDRAM和将显存中的data显示到屏幕上两者的关系,显存是40x2,屏幕是16x2,倘若我要 ...

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

使用道具 举报

发表于 2012-1-9 02:04:53 | 显示全部楼层
microseconds 是微秒 缩写是us 不是ms
回复 支持 反对

使用道具 举报

发表于 2012-2-20 19:14:43 | 显示全部楼层
树·水·风 发表于 2011-12-22 11:53
我不明白,把data写进显存DDRAM和将显存中的data显示到屏幕上两者的关系,显存是40x2,屏幕是16x2,倘若我要 ...

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

使用道具 举报

发表于 2012-2-20 22:51:22 | 显示全部楼层
ardyPro 发表于 2012-2-20 19:14
显存中上下两列都只能使用前16个地址,1602没法使用后面的,所以你写入第17列的数据没法自动显示,除非你 ...

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

使用道具 举报

发表于 2012-4-28 22:52:30 | 显示全部楼层
1602A 的8位接法显示正常。
但4位接法是乱码。。。。。不知那里出问题了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-4-29 09:29:04 | 显示全部楼层
xpaul 发表于 2012-4-28 22:52
1602A 的8位接法显示正常。
但4位接法是乱码。。。。。不知那里出问题了

{:soso_e103:} 仔细检查检查线序
回复 支持 反对

使用道具 举报

发表于 2012-4-29 17:45:29 | 显示全部楼层
检查过线序,还是一样。
回复 支持 反对

使用道具 举报

发表于 2012-4-29 17:50:29 | 显示全部楼层
本帖最后由 xpaul 于 2012-4-29 17:51 编辑

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2012-4-29 17:52:35 | 显示全部楼层


  1. /*
  2.    LiquidCrystal Library - Hello World

  3. Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
  4. library works with all LCD displays that are compatible with the
  5. Hitachi HD44780 driver. There are many of them out there, and you
  6. can usually tell them by the 16-pin interface.

  7. This sketch prints "Hello World!" to the LCD
  8. and shows the time.

  9. The circuit:
  10. * LCD RS pin to digital pin 12
  11. * LCD Enable pin to digital pin 11
  12. * LCD D4 pin to digital pin 5
  13. * LCD D5 pin to digital pin 4
  14. * LCD D6 pin to digital pin 3
  15. * LCD D7 pin to digital pin 2
  16. * LCD R/W pin to ground
  17. * 10K resistor:
  18. * ends to +5V and ground
  19. * wiper to LCD VO pin (pin 3)

  20. Library originally added 18 Apr 2008
  21. by David A. Mellis
  22. library modified 5 Jul 2009
  23. by Limor Fried ([url]http://www.ladyada.net[/url])
  24. example added 9 Jul 2009
  25. by Tom Igoe
  26. modified 22 Nov 2010
  27. by Tom Igoe

  28. This example code is in the public domain.

  29. [url]http://www.arduino.cc/en/Tutorial/LiquidCrystal[/url]
  30. */

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

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

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

  41. void loop() {
  42.   // set the cursor to column 0, line 1
  43.   // (note: line 1 is the second row, since counting begins with 0):
  44.   lcd.setCursor(0, 1);
  45.   // print the number of seconds since reset:
  46.   lcd.print(millis()/1000);
  47. }
复制代码



只是要用到LiquidCrystal.h库文件,和R/W接地了,改变了2,3,4,5Pin脚输出。{:soso_e113:}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-18 19:36 , Processed in 0.062978 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表