液晶(LiquidCrystal) 是一种高分子材料,因为其特殊的物理、化学、光学特性,20世纪中叶开始广泛应用在轻薄型显示器上。
液晶显示器(LiquidCrystalDisplay,LCD)的主要原理是以电流刺激液晶分子产生点、线、面并配合背部灯管构成画面。为叙述简便,通常把各种液晶显示器都直接叫做液晶。
各种型号的液晶通常是按照显示字符的行数或液晶点阵的行、列数来命名的。比如:1602的意思是每行显示16个字符,一共可以显示两行;类似的命名还有0801, 0802,1601等,这类液晶通常都是字符型液晶,即只 能显示ASCII码字符,如数字、大小写字母、各种符号等。12232液晶属于图形型液晶,她的意思是液晶由122列、32行组成,即共有122X32个点来显示各种图形,我们可以通过程序控制这122X32个点中的任一个点显示或不显示。类
似的命名还有12864,19264,192128,320240等,根据客户需要,厂家可以设计出任意数组合的点阵液晶。
液晶体积小、功耗低、显示操作简单,但是它有一个致命的弱点,其使用的温度范围很窄,通用型液晶正常工作温度范围为0°C+55°C,存储温度范围为-20°C+60°C,即使是宽温级液晶,其正常工作温度范围也仅为-20°C+70°C,存储温度范围为-30°C+80°C,因此在设计相应产品时,务必要考虑周全,选取合适的液晶。
本章主要介绍三种具有代表性的常用液晶,同时详细讲解并行操作方式和串行操作方式。市场上使用的1602液晶以并行操作方式居多,但也有并、串口同时具有的,用户可以选择用并口或串口操作。12232液晶同样也有这两种操作方式。只有并行接口的1602液晶接口如图7.1.1所示,其显示状态如图7.1.2所示。并、串口兼有的12232液晶接口如图7.1.3所示,其显示状态如图7.1.4所示
12864液晶串行接口与并行接口共用,用户可选择其中一种方式操作,其接口图如图7.1.5所示,其显示状态如图7.1.6所示。
1602液晶的讲解以并行操作为主,设计两个程序,一个是在液晶的任意位置显示字符,另一个是滚动显示一串字符。
本教材实验使用的1602液晶为5V电压驱动,带背光,可显示两行,每行16个字符,不能显示汉字,内置含128个字符的ASCII字符集字库,只 有并行接口,无串行接口。
1、接口信号说明
1602型液晶接口信号说明如表7.2.1所示。
2、主要技术参数(见表 7.2.2 )
3、基本操作时序
读状态 输入:RS=L, R/W=H, E=H 输出:D0~D7=状态字。
读数据 输入:RS=H, R/W=H, E=H 输出:无。
写指令 输入:RS=L, R/W=L, D0~D7=指令码,E=高脉冲 输出:DO, D7=数据。
写数据 输入:RS=H, R/W=L, D0~D7=数据, E=高脉冲 输出:无。
4、RAM地址映射图
控制器内部带有80B的RAM缓冲区,对应关系如图7.2.1所示。
当我们向图7.2.1中的000F、404F地址中的任一处写入显示数据时,液晶都可立即显示出来,当写入到1027或5067地址处时,必须通过移屏指令将它们移入可显示区域方可正常显示。
5、状态字说明(见表7.2.3)
注意:原则上每次对控制器进行读/写操作之前,都必须进行读/写检测,确保STA7为0。实际上,由于单片机的操作速度慢于液晶控制器的反应速度,因此可以不进行读/写检测,或只进行简短延时即可。
6、数据指针设置
控制器内部设有一个数据地址指针,用户可以通过它们访问内部的全部80B的RAM,如表7.2.4所示。
7、其他设置(见表 7.2.5 )
8、初始化设置
(1) 显示模式设置(见表 7.2.6)
(2) 显示开/关及光标设置(见表 7.2.7)
9、写操作时序(见图 7.2.2)
分析时序图可知操作 1602液晶的流程如下:
(1) 通过RS 确定是写数据还是写命令。写命令包括使液晶的光标显示/不显 示、光标闪烁/不闪烁、需/不需要移屏、在液晶的什么位置显示,等等。写数据是指要显示什么内容。
(2) 读/写控制端设置为写模式,即低电平。
(3) 将数据或命令送达数据线上。
(4) 给E一个高脉冲将数据送入液晶控制器,完成写操作。
关于时序图中的各个延时,不同厂家生产的液晶其延时不同,我们无法提供准确数据,大多数基本都为纳秒级,单片机操作最小单位为微秒级,因此我们在写程序时可不做延时,不过为了使液晶运行稳定,最好做简短延时,这需要大家自行测试以选定最佳延时。
TX-1C实验板上1602液晶与单片机接口如图7.2.3所示。
接口说明如下:
(1) 液晶1,2端为电源;15,16为背光电源;为防止直接加5V电压烧坏背光灯,在15脚串接一个10Ω电阻用于限流。
(2) 液晶3端为液晶对比度调节端,通过一个10kΩ电位器接地来调节液晶显示对比度。首次使用时,在液晶上电状态下,调节至液晶上面一行显示出黑色小格为止。
(3) 液晶4端为向液晶控制器写数据/写命令选择端,接单片机的P3.5口。
(4) 液晶5端为读/写选择端,因为我们不从液晶读取任何数据,只向其写入命令和显示数据,因此此端始终选择为写状态,即低电平接地。
(5) 液晶6端为使能信号,是操作时必需的信号,接单片机的P3.4口。
【例7.2.1】用C语言编程,实现在1602液晶的第一行显示"123456789Sumjess",在第二行显示" 1 00:00:00 "。新建文件Sumjess2.5_1.c,程序代码如下:
#include //编译器自带的库用 < > 编译器包含C52的定义
#include //编译器自带的库用 < > 循环移位函数等
#include //编译器自带的库用 < > 标准输入输出函数
#include //编译器自带的库用 < > C语言标准库函数
#include "delay_Sum.h" //后加的库用 “ ” 延时函数、显示器延时函数
#include "74hc595_Sum.h" //后加的库用 “ ” 74hc595芯片操作
#include "boardinit_Sum.h" //后加的库用 “ ” 数码管硬件芯片定义
#include "1602_Sum.h" //后加的库用 “ ” 1602函数
void main()
{
char e[16]={"123456789Sumjess"};
uchar m=0;
boardinit(); //数码管硬件初始化
lcdinit_1602(); //1602初始化
while(1)
{
m=rand();
Disp_1602(1,1,e,16);
Disp_1602(1,2," 00:00:00 ",16);
write_twoline_1602(2,(int)m);
delay(1000);
}
}
库函数如下:
/*
* 文 件 名:1602led.c.c
* 芯 片:1602液晶
* 晶 振:11.0592MHz
* 创 建 者:XK
* 创建日期:2011.8.6
* 修 改 者:
* 修改日期:
* 功能描述:1602,写数据函数
*/
#include
#include "1602_Sum.h"
#include "delay_Sum.h"
#include "74hc595_Sum.h"
sbit rs_1602=P2^5; //1602rs信号
sbit rw_1602=P2^6; //1602rw信号
sbit e=P2^4;
/*
void write_zl(uchar zl)
{
rs=0;
P0=zl;
delay(5);
e=1;
delay(5);
e=0;
}
void write_sj(uchar sj)
{
rs=1;
P0=sj;
delay(5);
e=1;
delay(5);
e=0;
} */
void write_order_1602(uchar order_data)
{
e=0;
rs_1602=0;
P0=order_data;
e=1;
delay(1);
e=0;
}
void write_data_1602(uchar data_1602)
{
e=0;
rs_1602=1;
P0=data_1602;
e=1;
delay(1);
e=0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//功能:按指定位置显示一串字符
///////////////////////////////////////////////////////////////
//输入: ////////
//列显示地址x_1602(取值范围1-16) ////////
//行显示地址y_1602(取值范围1-2), ////////
//指定字符串指针*p_1602, ////////
//要显示的字符个数count_1602 (取值范围1-16) ////////
///////////////////////////////////////////////////////////////
// 子函数使用例子: Disp_1602(1,1," TEMP: . ",16); //在1602第一行第一列写16个字符,既字符串数据
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Disp_1602(unsigned char x_1602,unsigned char y_1602,unsigned char *p_1602,unsigned char count_1602)
{
unsigned char i;
for(i=0;i
分析如下:
① 写命令操作和写数据操作分别用两个独立的函数来完成,函数内部唯一的区别就是液晶数据命令选择端的电平,写命令函数解释如下:
void write_com(uchar com)
{
lcdrs=0; //选择写命令模式
P0=com;//将要写的命令字送到数据总线上
delay(5);//稍做延时以待数据稳定
lcden=1;//使能端给一高脉冲,因为初始化函数中已经将lcden置为0
delay(5);//稍做延时
lcden=0;//将使能端置0以完成高脉冲
}
② 初始化函数中几个命令的解释请对照前面的指令码及功能说明。
write_com(0x38); //设置16X2显示,5X7点阵,8位数据接口
write_com(0x0c); //设置开显示,不显示光标
write_com(0x06); //写一个字符后地址指针自动加1write_com(0x01); //显示清0, 数据指针清0
③ 进入主函数,执行完初始化函数后,用"write_com(0x80);"命令先将数据指针定位到第一行第一个字处,然后写完第一行要显示的字,在每两个字之间做简短延时,这个时间可自行测试,时间太长会影响写入及显示速度,时间太短会影响控制器接收数据的稳定性,以测试稳定为最佳。
④ 当写第二行时需要重新定位数据指针:write_com(0x80+0x40)。
例7.2.1实际现象效果图如图7.2.4所示。
分析如下:
① 在写第一行数据前先定位数据指针"write_com(0x80+0x10);",将数据写在液晶第一行非显示区域地址处,写第二行时同样用’'write_com(0x80+0x10);"定位数据指针,这样写的目的是在接下来要使用移屏命令将液晶整屏向左移动。
② "write_com(0x18);"为整屏左移指令,每间隔200ms移动l个地址,共移动16个地址,刚好将要显示的数据全部移入液晶可显示区域。
③ 0x07指令也可完成移屏功能,大家可自行做实验验证。
例7.2.2实际现象效果图如图7.2.5所示。
12232液晶的讲解以串行操作为主,设计两个程序,一个是在液晶的任意位置显示数字、符号和汉字,另一个是滚动显示一串字符。
本教材实验使用的12232液晶为5V电压驱动,带背光,内置含8192个汉字的16X16点汉字库和含128个字符的16X8点ASCII字符集。该液晶主要由行驱动器、列驱动器及128X32全点阵液晶显示器组成可完成图形显示,也可以显示7.5X2个(16X16点阵)汉字,与外部CPU接口采用并行或串行两种控制方式。
1、接口信号说明
12232液晶并行接口信号说明如表7.3.1所示。
12232液晶串行接口信号说明如表7.3.2所示。
2、主要技术参数(见表7.3.3)
3、井行基本操作时序
读状态 输入:RS=L, R/W=H,E=H 输出:D0~D7=状态字。
读数据 输入:RS=H,R/W=H,E=H 输出:无。
写指令 输入:RS=L, R/W=L, D0-D7=指令码,E=高脉冲 输出:D0~D7=数据。
写数据 输入:RS=H,R/W=L, D0-D7=数据, E=高脉冲 输出:无。
4、忙标志(BF)
BF标志提供内部工作情况。BF=1表示模块在进行内部操作,此时模块不接受外部指令和数据。BF=0时,模块为准备状态,随时可接受外部指令和数据。
利用STATUSRD指令,可以将BF读到DB7总线来检验模块的工作状态。
5、字型产生ROM(CGROM)
字型产生ROM(CGROM)提供8192个触发器,用千模块内部屏幕显示开/关控制。DFF=1为开显示(DISPLAYON),此时将DDRAM 的内容显示在屏幕上。DFF=O为关显示(DISPLAY
OFF)。DFF状态是由指令DISPLAYON/OFF和RST信号控制的。
6、显示数据RAM(DDRAM)
模块内部显示数据RAM提供64X2个位元组空间,最多可控制4行16字(64个字)的中文字型显示(本模块只用到其中的7.5X2 个)。当写入显示数据RAM时,可分别显示CGROM与CGRAM字型。此模块可显示三种字型,分别是瘦长的英数字型(16X8)、CGRAM字型及CGROM中文字型。三种字型的选择,由DDRAM中写入的编码选择,在000F的编码中将选择CGRAM的定义,107F的编码中将选择瘦长英数字的字型,至于A0以上的编码自动地结合下一个位元组,组成两个位元组的编码,形成中文字型编码(A140~D75F)。
7、字型产生RAM(CGRAM)
字型产生RAM提供图像定义(造字)功能,可以提供4组16X16点的自定义图像空间,使用者可以将内部字型没有提供的图像字型自行定义到CGRAM中,便可和CGROM中定义过的字型一样,通过DDRAM显示在屏幕上。
8、地址计数器AC
地址计数器用来存储DDRAM/CGRAM的地址,它可由设定指令暂存器来改变,之后只要读取或写入DDRAM/CGRAM的值,地址计数器就会自动加1,当RS=O且Rfvi=l时,地址计数器的值会被读取到DB6DBO中。 .
9、游标/闪烁控制电路
此模块提供硬件游标及闪烁控制电路,由地址计数器的值来指定DDRAM中的游标或闪烁位置。
10、状态字说明(见表7.3.4)
注意:原则上每次对控制器进行读/写操作之前,都必须进行读/写检测,确保STA7为0。实际上,由千单片机的操作速度低于液晶控制器的反应速度,因此可以不进行读/写检测,或只进行简短延时即可。
11、指令说明(见表7.3.5)
另外,当RE=1时,还有一些扩充指令可设定液晶的一些功能,如待机模式、卷动地址开关开/启、反白显示、睡眠、控制功能设定、绘图模式、设定绘图RAM地址等,关于这部分扩展功能请大家查阅相关资料,这里不再赘述。
12、井行写操作时序(见图7.3.1)
13、串行读/写操作时序(见图7.3.2)
由于122332液晶的并行操作方式基本与1602液晶相同,所以不再讲述,本节主要讲解12232液晶的串行操作方式,这里重点讲解串行时序。
(1) CS—液晶的片选信号线,每次在进行数据操作时都必须将CS端拉高。
(2) SCLK—串行同步时钟线,每操作一位数据都要有一个SCLK跳变沿,而且在这里是上升沿有效。也就是说,每次SCLK由低电平变为高电平的瞬间,液晶控制器将SID上的数据读入或输出。
(3) SID—串行数据,每一次操作都由三个字节数据组成,第一字节向控制器发送命令控制字,告诉控制器接下来是什么操作,若为写指令则发送11111000,若为写数据则发送11111010。第二字节的高4位发送指令或数据的高4位,第二字节的低4位补0。第三字节的高4位发送指令或数据的低4位,第三字节的低4位同样补0。
12232液晶的串行接口非常简单,只需要三条线与单片机的任意三个I/O口相连即可操作,图7.3.3为12232的最简单接线图,这里我们没有加入背光,3端的对比度调节端接一10kΩ电位器的滑动端,电位器另两端分别接Vcc和GND,注意这里和1602液晶有所不同,现在市面上也有部分12232液晶不需要调节对比度,出厂时已经设定好。SCLK,SID,CS三条线与单片机的任意I/O口相连,TX-1C实验板上连接方式见源程序。
分析如下:
(1) 发送命令和发送数据分别用"send_command()"和"send_data()"函数实现,由前面的描述可知,无论是发送一条命令还是发送一条数据都是由三个字节组成,若发送指令则第—个字节为0xf8,若发送数据则第一个字节为0xfa,从上面两个函数可看出,它们的不同之处也就在这里。
(2) "SID=(bit)(i_data&0x80);"中(bit)表示将后面括号里的数强制转换成位,当把一个字节强制转换成一位时使用(bit),这里只取这个字节的最高位。整条语句的意思是,将i_data的最高位取出来赋给SID。然后通过下面的"i_data=i_data<<1;"依次将i_data的每一位从高到低在SCLK的作用下送给SID,从而发送给液晶。
(3) "i_data=command_data;"和"i_data&=0xf0;"这两句的意思是,将所发送字节的高4位取出,低4位补0。
"i_data=command_data;"和"i_data<<=4;"这两句的意思是,将所发送字节的低4位移到高4位的位置上,原来的低4位自动补0。
(4) "lcd_init()“是对12232液晶的初始化设置,只有对液晶进行了正确的初始化设置,液晶才可正常运行。
其实际效果如图7.3.4所示。
【例7.3.2】用C语言编程,实现第一行从右侧移入"Hello everyone!”,同时第二行从右侧移入“欢迎大家来学习!,"移入速度自定,最后停留在屏幕上。新建文件Sumjess2.5_4.c,程序代码如下:
分析如下:
(1) 由于12232液晶没有专门的移屏指令,因此我们使用for循环来实现移屏效果,实际上这种效果是重复向不同的地方写入显示字符而实现的。用这种方法看上去是从右往左移动,也可以使它从左向右移动。
(2) "delay_lms(300);"这个延时函数决定屏幕移动的速度,大家可做测试,自行调节。其实际效果如图7.3.5所示。
12864液晶操作方法与7.3节12232液晶操作方法非常相似,本节讲解其并行操作方法,设计一个程序,在液晶的任意位置显示数字、符号和汉字。
本教材实验用12864液晶使用ST7920控制器,5V电压驱动,带背光,内置8192个16X16点阵、128个字符(8X16点阵)及64X256点阵显示RAM(GDRAM)。与外部CPU接口采用并行或串行两种控制方式。
1、接口信号说明
12864液晶接口信号说明如表7.4.1所示。
2、主要技术参数(见表7.4.2)
4、忙标志(BF)
BF标志提供内部工作情况,BF=1表示模块在进行内部操作,此时模块不接受外部指令和数据。BF=0时,模块为准备状态,随时可接受外部指令和数据。
利用STATUSRD指令,可以将BF读到DB7总线来检验模块的工作状态。
5、状态字说明(见表7.4.3)
注意:原 则上每次对控制器进行读/写操作之前,都必须进行读/写检测,确保STA7为0。实际上,由千单片机的操作速度低千液晶控制器的反应速度,因此可不必进行读/写检测,或只进行简短延时即可。
6、指令说明(见表7.4.4)
另外,当RE=1时,还有一些扩充指令可设定液晶功能,如待机模式、卷动地址开关开启、反白显示、睡眼、控制功能设定、绘图模式、设定绘图RAM地址等,下面详细解释各个指令。
7、指令详解:
8、显示坐标关系
(1) 图形显示坐标
水平方向X以字为单位,垂直方向Y以位为单位。
绘图显示RAM提供128X8B的记忆空间,在更改绘图RAM时,先连续写入水平与垂直的坐标值,再写入两个字节的数据,而地址计数器(AC)会自动加l;在写入绘图RAM期间,绘图显示必须关闭。写入绘图RAM的步骤如下:
① 关闭绘图显示功能。
② 先将水平的位元组坐标(CX)写入绘图RAM地址。
③ 再将垂直的坐标(Y)写入绘图RAM地址。
④ 将D15~D8写入到RAM中。
⑤ 将D7~D0写入到RAM中。
⑥ 打开绘图显示功能,绘图显示缓冲区分布如图7.4.1 绘图显示坐标所示。
(2) 汉字显示坐标(见表7.4.5)
9、井行写操作时序(见图7.4.2)
10、串行读/写操作时序(见图7.4.3)
对比7.3节12232液晶的时序图可知,无论是并行操作还是串行操作,12864液晶与12232液晶几乎完全一样。
12864液晶的串行接口也非常简单,并行连接到TX-lC实验板上原理图如图7.4.4所示。
【例7.4.1】
#include //编译器自带的库用 < > 编译器包含C52的定义
#include //编译器自带的库用 < > 循环移位函数等
#include //编译器自带的库用 < > 标准输入输出函数
#include //编译器自带的库用 < > 字符串处理函数
#include "delay_Sum.h" //后加的库用 “ ” 延时函数、显示器延时函数
#include "74hc595_Sum.h" //后加的库用 “ ” 74hc595芯片操作
#include "boardinit_Sum.h" //后加的库用 “ ” 数码管硬件芯片定义
#include "12864_Sum.h" //后加的库用 “ ” 12864函数
unsigned char code IC_DAT[]={
"----欢迎使用----"
" QQ:1371129880 "
" 博客:Sumjess "
" 祝你学习愉快 "
};
unsigned char code IC_DAT2[]={
"我爱你时, "
"我不爱你时, "
"你是那么的闪耀 "
"你什么都不是。 "
};
void main()
{
boardinit(); //数码管硬件初始化
while(1)
{
initinal();//调用LCD字库初始化程序
delay(5);
lcd_mesg(IC_DAT);
delayms(300); //延时程序必要的,长与短,自己调节
initinal();
delay(5);
lcd_mesg(IC_DAT2);
delayms(300);
}
}
库函数:
#include
#include "12864_Sum.h"
#include "74hc595_Sum.h"
sbit RS = P2^5; //注意:一定要看12864液晶模块的资料,来确定怎样操作
sbit WRD = P2^6;
sbit E = P2^4;
sbit PSE = P1^3;
sbit RES = P1^5;
void lcd_mesg(unsigned char code *addr1) //显示汉字函数,8*4=32
{
unsigned char i;
TransferData(0x80,0);
delay(100);
for(i=0;i<32;i++)
{
TransferData(*addr1,1);
addr1++;
}
TransferData(0x90,0);
delay(100);
for(i=32;i<64;i++)
{
TransferData(*addr1,1);
addr1++;
}
}
void TransferData(char data1,bit DI) //传送数据或是命令,当DI=0时,传送命令,当DI=1时,传送数据
{
WRD=0;
RS=DI;
P0=0XFF;
P0=data1;
E=1;// 置12684 使能端 E=1;
delay(1);
E=0;// 置12684 使能端 E=0;
}
void initinal(void) //初始化,12864有要求的要写上
{
PSE=1; //并口工作模式
RES=0; //复位
RES=1; //复位置高
TransferData(0x30,0);
TransferData(0x30,0);
TransferData(0x08,0);
TransferData(0x10,0);
TransferData(0x0C,0);
TransferData(0x01,0);
TransferData(0x06,0);
}
分析如下:
(1) 写命令和写数据分别用两个函数"write_cmd()"和"write_dat()"来实现,由千其并行操作时序与1602液晶一样,这里不再讲解。
(2) "lcd_pos()"函数用来设定液晶上显示的位置。12864液晶一共可以显示4行,每行可以显示8个汉字或16个字符,每一个汉字位置都有固定的地址,设置不同的地址即可在不同的位置上显示字符,关千其显示位置及地址请参照前面的汉字显示坐标。
(3) i=0;
while(dis2[i]!=’\0’)
{
write_dat(dis2[i]); //显示字符
1++;
}
上面程序段实现的功能是,将数组dis2[]中的所有字符一个个地显示在液晶屏幕上。程序执行时,依次查询数组dis2[]中的所有元素,当查到一个“空”时,退出此while循环语句,
“空”在存储器中的存储形式是\0’'如果数组中有8个元素,那么第9个元素即为“空”。
(4) "makerand()"函数生成10个随机数,然后把这10个随机数存在数组dist[]中。实际上,在函数中只调用了两次随机数生成函数,产生了两个5位的随机数,然后再将这两个5位的随机数分别取出存储在数组中。关千随机数生成函数的介绍请看下一个知识点。
打开Keil\C51\HLP文件夹下的C51lib.chm文件,在索引文件夹下输入"rand",详细内容如下:
rand()函数生成一个0-32767之间的伪随机数,函数运行完后将返回这个伪随机数,另外还可以看到void srand(inseed); /ran,domnumbergeneratorseed/
srand(int seed)函数可设置一个初值,然后调用rand()函数生成一个初值与32767之间的随机数。如:
int a;
srand(200);
a=rand();
这时,a的值将是200-32767之间的一个随机数,大家可自行写程序测试,看如何写一个函数让它生成0-10或0-100之间的随机数。
图7.4.5为例7.4.1实例效果图