本文为大大维原创,最早于博客园发表,转载请注明出处!!!

一、前言:

  LCD ( Liquid Crystal Display 的简称)液晶显示器,已经逐渐替代CRT成为主流的显示设备之一,因此也成为了单片机发烧友绕不过的话题之一;而LCD1602更是很多单片机发烧友最早接触的字符型液晶显示器。笔者经过一段时间的深入学习,对其驱动有了些许心得,特地记录于此,以备以后查阅。

  LCD1602,也叫1602液晶,是一种专门用来显示字母、数字、符号等的点阵型液晶模块,工业字符型液晶的一种,能够同时显示16x02即32个字符。主控芯片是HD44780或者其它兼容芯片,而市面上字符液晶大多数是基于HD44780液晶芯片的,控制原理是完全相同的。因此尽管LCD1602可显示的内容十分有限,但在此花点时间是完全值得的。

二、LCD的一些背景知识:

<1>LCD1602基本参数及引脚功能:

1.LCD1602的分类:

  LCD1602分为带背光和不带背光两种,带背光的比不带背光的厚,是否带背光在应用中并无差别,两者尺寸差别如下图10-54所示:

在本文中,笔者选用的是带背光的一种。

  

2.基本参数:

显示容量:16×2个字符

芯片工作电压:4.5—5.5V

工作电流:2.0mA(5.0V)

模块最佳工作电压:5.0V

字符尺寸:2.95×4.35(W×H)mm

2.引脚功能说明

  1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下:

编号

符号

引脚说明

编号

符号

引脚说明

1

VSS

电源地

9

D2

数据

2

VDD

电源正极

10

D3

数据

3

VL

液晶显示偏压

11

D4

数据

4

RS

数据/命令选择

12

D5

数据

5

R/W

读/写选择

13

D6

数据

6

E

使能信号

14

D7

数据

7

D0

数据

15

BLA

背光源正极

8

D1

数据

16

BLK

背光源负极

各引脚说明:

第1脚:VSS为地电源。

第2脚:VDD接5V正电源。

第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

第7~14脚:D0~D7为8位双向数据线。

第15脚:背光源正极。

第16脚:背光源负极

<2>LCD1602的指令说明及时序

1.与HD44780相兼容的芯片时序表如下:

读状态

输入

RS=L,R/W=H,E=H

输出

D0—D7=状态字

写指令

输入

RS=L,R/W=L,D0—D7=指令码,E=高脉冲

输出

读数据

输入

RS=H,R/W=H,E=H

输出

D0—D7=数据

写数据

输入

RS=H,R/W=L,D0—D7=数据,E=高脉冲

输出

2.LCD1602的指令说明:

  1602液晶模块内部的控制器共有11条控制指令,如表所示:

序号

指令

RS

R/W

D7

D6

D5

D4

D3

D2

D1

D0

1

清显示

0

0

0

0

0

0

0

0

0

1

2

光标返回

0

0

0

0

0

0

0

0

1

*

3

置输入模式

0

0

0

0

0

0

0

1

I/D

S

4

显示开/关控制

0

0

0

0

0

0

1

D

C

B

5

光标或字符移位

0

0

0

0

0

1

S/C

R/L

*

*

6

置功能

0

0

0

0

1

DL

N

F

*

*

7

置字符发生存贮器地址

0

0

0

1

字符发生存贮器地址

8

置数据存贮器地址

0

0

1

显示数据存贮器地址

9

读忙标志或地址

0

1

BF

计数器地址

10

写数到CGRAM或DDRAM

1

0

要写的数据内容

11

从CGRAM或DDRAM读数

1

1

读出的数据内容

笔者在百度文库中发现一个特别好的介绍1602指令集的文章,给大家分享如下:

点击查看

<3>LCD1602的RAM地址映射及标准字库表

1.LCD1602的RAM地址映射

  液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,下图是1602的内部显示地址:

在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。

2.LCD1602的标准字库表

  1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如下图所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等。

在使用标准字库中的字符图形时,无需自己制作字模即可直接使用,若要显示汉字等标准字库中没有的元素,则需要自己在DDRAM中制作字模。

<4>LCD1602四线驱动的约定流程

1、  写入指令:

1) EN = 0 (LCD使能禁止)

2) 短延时

3) RS = 0  ,RW = 0  (准备写入指令)

4) DATA = 指令的高4位(ATA代表D7、D6、D5、D4,下同)

5) 短延时

6) EN = 1 (LCD使能允许,指令写入)

7) 短延时

8) EN = 0 (LCD使能禁止)

9) DATA = 指令的低4位

10) 短延时

11) EN = 1 (LCD使能允许,指令写入)

12) 短延时

13) EN = 0 (LCD使能禁止)

14) 短延时

2、  写入数据:

1) EN = 0 (LCD使能禁止)

2) 短延时

3) RS = 1 ,RW = 0 (准备写入数据)

4) DATA = 数据的高4位

5) 短延时

6) EN = 1 (LCD使能允许,数据写入)

7) 短延时

8) EN = 0 (LCD使能禁止)

9) DATA = 数据的低4位

10) 短延时

11) EN = 1 (LCD使能允许,数据写入)

12) 短延时

13) EN = 0 (LCD使能禁止)

14) 短延时

三、关于LCD控制库LiquidCrystal:

  LiquidCrystal是Arduino的官方库之一,他可以控制基于日立公司HD44780(或兼容)芯片集成的字符型LCD。该库可以通过四线或者八线模式控制LCD。

无疑,LiquidCrystal库可以使LCD的控制编程变得十分简单!!!

笔者在学习中,发现了一个比较完整的LiquidCrystal库的中文资料,链接如下:

点击查看

下面,就一些常用的LiquidCrystal库函数做一个简单介绍:

1.LiquidCrystal()构造函数

2.begin()指定显示方式

3.clear()清屏,光标置于左上角

4.home()接下来的字符从左上角显示

5.setCursor(col,row)设置光标位置

6.print()LCD显示字符

四、Arduino下的LCD1602的8线驱动模式:

<1>优缺点

 八线模式的优点是每位数据均从单独的数据线传输,因此数据传输速度快。但缺点也是显然的,需要占掉大量的端口。

<2>接线方式

VL为液晶显示器对比度调整端,有条件的话,最好使用一个10K的电位器来调整对比度。限于条件,笔者通过反复调试,最后选择了4k电阻,效果也还可以。

<3>试验代码

1.不使用LiquidCrystal库

 /*Arduino在8位接法下不使用LiquidCrystal库
* 输出欢迎界面和Hello World!
* 作者:大大维
* 2016/10/23
*/ int RS = ; //数据/命令选择器引脚(RS)
int RW = ; //读/写选择器引脚(R/W)
int DB[] = {, , , , , , , }; //使用数组来定义总线需要的管脚(D0-D7)
int Enable = ; //使能(E) void LcdCommandWrite(int value) {
// 定义所有引脚
int i = ;
digitalWrite(RS, LOW);
digitalWrite(RW, LOW);
for (i=DB[]; i <= RS; i++) //总线赋值
{
//这里的&是二进制的“与”运算。取指令码的最低位。
digitalWrite(i,value & 0x01);
value >>= ;
}
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,HIGH);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
} void LcdDataWrite(int value) {
// 定义所有引脚
int i = ;
digitalWrite(RS, HIGH);
digitalWrite(RW, LOW);
for (i=DB[]; i <= DB[]; i++) {
digitalWrite(i,value & 0x01);
value >>= ;
}
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,HIGH);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
} void setup (void) {
int i = ;
for (i=Enable; i <= RS; i++) {
pinMode(i,OUTPUT);
}
delay();
// 短暂的停顿后初始化LCD
// 用于LCD控制需要
LcdCommandWrite(0x38); // 设置为8-bit接口,2行显示,5x7文字大小
delay();
LcdCommandWrite(0x06);   // 输入方式设定,自动增量,画面没有移位
delay();
LcdCommandWrite(0x0C);   // 显示设置,开启显示屏,光标关,无闪烁
delay();
} void loop (void) {
LcdCommandWrite(0x01);   // 屏幕清空,光标位置归零
delay();
LcdCommandWrite(0x80+);   // 定义光标位置为第一行第五个位置
delay();
// 写入欢迎信息
LcdDataWrite('W');
LcdDataWrite('e');
LcdDataWrite('l');
LcdDataWrite('c');
LcdDataWrite('o');
LcdDataWrite('m');
LcdDataWrite('e');
delay();
LcdCommandWrite(0xc0+);   // 定义光标位置为第二行第二个位置
delay();
LcdDataWrite('I');
LcdDataWrite(' ');
LcdDataWrite('a');
LcdDataWrite('m');
LcdDataWrite(' ');
LcdDataWrite('D');
LcdDataWrite('a');
LcdDataWrite('D');
LcdDataWrite('a');
LcdDataWrite('W');
LcdDataWrite('e');
LcdDataWrite('i');
delay();
LcdCommandWrite(0x01);    // 屏幕清空,光标位置归零
delay();
LcdCommandWrite(0x80+);   //定义光标位置为第一行第二个位置
delay();
LcdDataWrite('H');
LcdDataWrite('e');
LcdDataWrite('l');
LcdDataWrite('l');
LcdDataWrite('o');
LcdDataWrite(' ');
LcdDataWrite('W');
LcdDataWrite('o');
LcdDataWrite('r');
LcdDataWrite('l');
LcdDataWrite('d');
LcdDataWrite('!');
delay();
}

看到上面的代码,是否觉得略显复杂?但要是使用了LiquidCrystal库,一切将变得十分简单!!!

2.使用LiquidCrystal库

 /*Arduino在8位接法下使用LiquidCrystal库
* 输出欢迎界面和Hello World!
* 作者:大大维
* 2016/10/23
*/
#include<LiquidCrystal.h>
LiquidCrystal lcd(,,,,,,,,,);    //初始化LCD
void setup(){
lcd.begin(,);    //设置LCD为16列*2行
}
void loop(){
lcd.clear();     //清屏操作
lcd.setCursor(,);    //设置光标位置为第一行,第六列
lcd.print("Welcome");     //在LCD上输出信息
delay();    //延时程序
lcd.setCursor(,);
lcd.print("I am DaDaWei");
delay();
lcd.clear();
lcd.setCursor(,);
lcd.print("Hello World!");
delay();
}

<4>试验展示

演示视频

五、Arduino下的LCD1602的四线驱动模式:

<1>优缺点

 四线模式相对于八线模式的优点是占用的端口更少,减少了四条数据线,也就是说八位的数据需要通过四条线来发送,那么会导致四线模式比八线模式数据速度慢些。

<2>接线方式

<3>试验代码

1.不使用LiquidCrystal库

 /*Arduino在4位接法下不使用LiquidCrystal库
* 输出欢迎界面和Hello World!
* 作者:大大维
* 2016/10/23
*/ int RS = ; //数据/命令选择器引脚(RS)
int RW = ; //读/写选择器引脚(R/W)
int DB[] = {, , , }; //使用数组来定义总线需要的管脚(D0-D7)
int Enable = ; //使能(E) void LcdCommandWrite(int value) {
// 定义所有引脚
int i = ;
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
digitalWrite(RS, LOW);
digitalWrite(RW, LOW); /* 6 7 8 9
* D7 D6 D5 D4
* DB[0] DB[1] DB[2] DB[3]
*/
int temp=value & 0xf0;//取指令高4位
for (i=DB[]; i <= ; i++)
{
if((temp & 0x80)!=)//取指令最高位
digitalWrite(i,HIGH);
else
digitalWrite(i,LOW );
temp <<= ;
}
delayMicroseconds(); // 延时1us
digitalWrite(Enable,HIGH);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,LOW); temp=(value & 0x0f)<<;
for (i=DB[]; i <= ; i++)
{
if((temp & 0x80)!=)//取指令最高位
digitalWrite(i,HIGH);
else
digitalWrite(i,LOW );
temp <<= ;
}
delayMicroseconds(); // 延时1us
digitalWrite(Enable,HIGH);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
} void LcdDataWrite(int value) {
// 定义所有引脚
int i = ;
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
digitalWrite(RS, HIGH);
digitalWrite(RW, LOW);
int temp=value& 0xf0;
for (i=DB[]; i <= ; i++)
{
if((temp & 0x80)!=)//取指令最高位
digitalWrite(i,HIGH);
else
digitalWrite(i,LOW );
temp <<= ;
}
digitalWrite(Enable,HIGH);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,LOW); temp=(value & 0x0f)<<;
for (i=DB[]; i <= ; i++)
{
if((temp & 0x80)!=)//取指令最高位
digitalWrite(i,HIGH);
else
digitalWrite(i,LOW );
temp <<= ;
}
delayMicroseconds(); // 延时1us
digitalWrite(Enable,HIGH);
delayMicroseconds(); // 延时1us
digitalWrite(Enable,LOW);
delayMicroseconds(); // 延时1us
} void setup (void) {
int i = ;
for (i=Enable; i <= RS; i++) {
pinMode(i,OUTPUT);
}
delay();
// 短暂的停顿后初始化LCD
// 用于LCD控制需要
LcdCommandWrite(0x38); // 设置为8-bit接口,2行显示,5x7文字大小
delay();
LcdCommandWrite(0x06); // 输入方式设定,自动增量,画面没有移位
delay();
LcdCommandWrite(0x0C); // 显示设置,开启显示屏,光标关,无闪烁
delay();
} void loop (void) {
LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
delay();
LcdCommandWrite(0x80+); // 定义光标位置为第一行第五个位置
delay();
// 写入欢迎信息
LcdDataWrite('W');
LcdDataWrite('e');
LcdDataWrite('l');
LcdDataWrite('c');
LcdDataWrite('o');
LcdDataWrite('m');
LcdDataWrite('e');
delay();
LcdCommandWrite(0xc0+); // 定义光标位置为第二行第二个位置
delay();
LcdDataWrite('I');
LcdDataWrite(' ');
LcdDataWrite('a');
LcdDataWrite('m');
LcdDataWrite(' ');
LcdDataWrite('D');
LcdDataWrite('a');
LcdDataWrite('D');
LcdDataWrite('a');
LcdDataWrite('W');
LcdDataWrite('e');
LcdDataWrite('i');
delay();
LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
delay();
LcdCommandWrite(0x80+); //定义光标位置为第一行第二个位置
delay();
LcdDataWrite('H');
LcdDataWrite('e');
LcdDataWrite('l');
LcdDataWrite('l');
LcdDataWrite('o');
LcdDataWrite(' ');
LcdDataWrite('W');
LcdDataWrite('o');
LcdDataWrite('r');
LcdDataWrite('l');
LcdDataWrite('d');
LcdDataWrite('!');
LcdCommandWrite(0xc0); // 定义光标位置为第二行起始位置
delay();
LcdDataWrite('');
LcdDataWrite('-');
LcdDataWrite('B');
LcdDataWrite('i');
LcdDataWrite('t');
LcdDataWrite('-');
LcdDataWrite('I');
LcdDataWrite('n');
LcdDataWrite('t');
LcdDataWrite('e');
LcdDataWrite('r');
LcdDataWrite('f');
LcdDataWrite('a');
LcdDataWrite('c');
LcdDataWrite('e');
delay();
delay();
}

2.使用LiquidCrystal库

 /*Arduino在4位接法下使用LiquidCrystal库
* 输出欢迎界面和Hello World!
* 作者:大大维
* 2016/10/23
*/
#include<LiquidCrystal.h>
LiquidCrystal lcd(,,,,,,); //初始化LCD
void setup(){
lcd.begin(,); //设置LCD为16列*2行
}
void loop(){
lcd.clear(); //清屏操作
lcd.setCursor(,); //设置光标位置为第一行,第六列
lcd.print("Welcome"); //在LCD上输出信息
delay(); //延时程序
lcd.setCursor(,);
lcd.print("I am DaDaWei");
delay();
lcd.clear();
lcd.setCursor(,);
lcd.print("Hello World!");
lcd.setCursor(,);
lcd.print("4-Bit-Interface");
delay();
}

<4>试验展示

演示视频

Arduino下LCD1602综合探究(上)——1602的两种驱动方式,如何使LCD的控制编程变得更简单的更多相关文章

  1. Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法

    一.前言: 上文中,笔者系统的阐述了1602的两种驱动方式,并简单的提到了Arduino的LiquidCrystal库.本文紧接上文,对以下两个问题进行更加深入的探讨:如何能够使1602对Arduin ...

  2. PyCharm上unittest 测试用例两种执行方式

    每次讲到unittest测试框架的时候,经常有同学在群里反映,为啥我的运行不是按照我往suite里添加的用例顺序执行的,为什么别人的能跑出来报告,我的就不行... 当然,首先确认代码是OK的,如果代码 ...

  3. ListView下拉刷新及上拉更多两种状态

    一.前言: 很多应用都会用到ListView,当然如果是iOS就会用UITableViewController,这两个控件在不同的OS上,功能是一样的,只是有些细微的不同(iOS的UITableVie ...

  4. 探究Redis两种持久化方式下的数据恢复

    对长期奋战在一线的后端开发人员来说,都知道redis有两种持久化方式RDB和AOF,虽说大家都知道这两种方式大概运作方式,但想必有实操的人不会太多. 这里是自己实操两种持久化方式的一点点记录. 先看以 ...

  5. spring 第一篇(1-1):让java开发变得更简单(下)

    切面(aspects)应用 DI能够让你的软件组件间保持松耦合,而面向切面编程(AOP)能够让你捕获到在整个应用中可重用的组件功能.在软件系统中,AOP通常被定义为提升关注点分离的一个技术.系统由很多 ...

  6. 将HTML页面自动保存为PDF文件并上传的两种方式(一)-前端(react)方式

    一.业务场景 公司的样本检测报告以React页面的形式生成,已调整为A4大小的样式并已实现分页,业务上需要将这个网页生成PDF文件,并上传到服务器,后续会将这个文件发送给客户(这里不考虑). 二.原来 ...

  7. Java使用SFTP和FTP两种连接方式实现对服务器的上传下载 【我改】

    []如何区分是需要使用SFTP还是FTP? []我觉得: 1.看是否已知私钥. SFTP 和 FTP 最主要的区别就是 SFTP 有私钥,也就是在创建连接对象时,SFTP 除了用户名和密码外还需要知道 ...

  8. 软件公司的两种管理方式 总体来说,这个世界上存在两种不同的软件公司的组织结构。我把他们叫做 Widget Factory(小商品工厂) 和 Film Crews(电影工作组

    软件公司的两种管理方式 一个简单的回答应该是——“因为在我们的社会里,我们总是会认为薪水和会和职位的层次绑在一起”.但是,这个答案同时也折射出一个事实——我们的薪资是基于我们的所理解的价值,但这并没有 ...

  9. 探究Repository模式的两种写法与疑惑

    现如今DDD越来越流行,园子里漫天都是介绍关于它的文章.说到DDD就不能不提Repository模式了,有的地方也叫它仓储模式. 很多时候我们对Repository都还停留在Copy然后使用的阶段, ...

随机推荐

  1. BugFree 测试管理系统

    测试经理 分配 每个人的账号 新建bug -> bug已修复 -> 已验证 -> closed

  2. MVC路由配置例

    public static void RegisterRoutes(RouteCollection routes) { string suffix = string.Empty; routes.Ign ...

  3. 完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法

    完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法   HTML5的语义化标签以及属性,可以让开发者非常方便地实现清晰的web页面布局,加上CSS3的效果渲染,快速建立丰富灵活的web页 ...

  4. mysql使用load导入txt文件所遇到的问题及解决方法

    导入txt文件,有导入向导这种方式: 另外可以使用load的方式导入.最开始使用以下代码插入: load data local infile 'F:\\Data\\predict_data.txt' ...

  5. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  6. C#夯实基础之多线程三:线程的优先级

    一.为什么需要优先级--线程调度的问题 在现实生活中,优先级是一个很常见的现象:在火车站,如果你是孕妇,你是可以走进站中的专门绿色通道的,可以提前上火车以免拥挤:火警119匪警110出警的时候,都是人 ...

  7. links and softwares

    links 普通 http://www.ncpa-classic.com//special/2014gejujie/index.shtml ; 中国大剧院 http://tieba.baidu.com ...

  8. 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。系统发布第二天访问链接关闭问题。

    解决Mysql连接池被关闭  ,hibernate尝试连接不能连接的问题. (默认MySQL连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池. 所以系统发布第二天访问会 ...

  9. Python列表去除重复元素

    主要尝试了3种列表去除重复元素 #2.去除列表中的重复元素 #set方法 def removeDuplicates_set(nums): l2 = list(set(l1)) #用l1的顺序排序l2 ...

  10. java的异常总结

    异常:在java程序中也出现不正常的情况,这个就叫异常.java是面向对象的语言.任何事物都可以用类来描述,同样异常也是一种事物,java中提供了很多异常类 很多异常堆积起来叫做异常体系 Throwa ...