- AVR单片机很简单:C语言快速入门及开发实例
- 曹振华主编
- 3141字
- 2020-08-28 00:36:28
2.9 I/O口控制1602液晶显示应用实例
2.9.1 液晶屏基础知识
液晶的组成物质是一种有机化合物,是以碳为中心所构成的化合物,在常温下,液晶是处于固体和液体之间的一种物质,具有固体和液体物质的双重特性,利用液晶体的电光效应制作的显示器就是液晶显示器(LCD)。
LCD显示器需要由驱动芯片控制,控制芯片已经集成在显示器中了。最流行的驱动芯片是Hitachi(日立)公司的HD44780(或其他相应的芯片)。
LCD由灰色的像素组成。排列得非常小的灰点组成字符。一个典型的16×2LCD可在两行中显示16个字符,每个字符由5个像素宽、8个像素高组成。如果在显示器上把对比度设得很高,32组5×7像素将变得可见。
以TN型液晶显示器为例,将上下两块制作有透明电极的玻璃,利用胶框对四周进行封接,形成一个很薄的盒。在盒中注入TN型液晶材料。通过特定工艺处理,使TN型液晶的棒状分子平行地排列于上下电极之间,如图2-30所示。
图2-30 TN液晶显示器的基本构造
根据需要制作成不同的电极,就可以实现不同内容的显示。平时液晶显示器呈透亮背景,电极部位加电压后,显示黑色字符或图形,这种显示称“正显示”。如将图2-30中下偏振片转成与上偏振片的偏振方向一致装配,则正相反,平时背景呈黑色,加电压后显示字符部分呈透亮,这种显示称为“负显示”。后者适用于背光源的彩色显示器件。
2.9.2 1602 LCD液晶屏
1602字符液晶是最常用的一种,很具有代表性,其实物图2-31所示。最初的1602液晶使用的是HD44780控制器,现在各个厂家的1602模块基本上都是采用了与之兼容的IC,所以特性上基本都是一致的。
图2-31 1602 LCD液晶屏的实物
(1)1602 LCD显示屏概述
①技术参数
a.显示容量为16×2个字符;
b.芯片工作电压为4.5~5.5V;
c.工作电流为2.0mA(5.0V);
d.模块最佳工作电压为5.0V;
e.字符尺寸为2.95mm×4.35mm(W×H)。
②各引脚定义 1602 LCD采用标准14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表2-16所示。
表2-16 各引脚说明
第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)1602 LED液晶屏的指令及时序 1602液晶模块内部的控制器共有11条控制指令,如表2-17所示。
表2-17 1602控制指令表
1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。表2-17中,1为高电平,0为低电平。
指令1:清除显示,指令码01H,光标复位到地址00H位置。
指令2:光标复位,光标返回到地址00H。
指令3:光标和显示模式设置。I/D表示光标移动方向,高电平右移,低电平左移,S表示屏幕上所有文字是否左移或右移。高电平表示有效,低电平则无效。
指令4:显示开关控制。D用于控制整体显示的开、关,高电平表示开显示,低电平表示关显示。C用于控制光标的开、关,高电平表示有光标,低电平表示无光标。B用于控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:光标或显示移位。S/C用于在高电平时移动显示的文字,低电平时移动光标。
指令6:功能设置命令。DL在高电平时为4位总线,低电平时为8位总线。N在低电平时为单行显示,高电平时双行显示。F在低电平时显示5×7的点阵字符,高电平时显示5×10的点阵字符。
指令7:字符发生器RAM地址设置。
指令8:DDRAM地址设置。
指令9:读忙信号和光标地址。BF为忙标志位,高电平表示忙碌,此时模块不能接收命令或者数据,如果为低电平表示空闲。
指令10:写数据。
指令11:读数据。
与HD44780相兼容的芯片时序表如表2-18所示。
表2-18 基本操作时序表
读写操作时序如图2-32和图2-33所示。
图2-32 读操作时序
图2-33 写操作时序
(3)1602 LCD液晶屏的RAM地址映射及标准字库表 液晶显示模块显示较慢,所以在执行每条指令之前一定要确认模块的忙标志是否为低电平,如果忙标志为低电平则表示空闲,否则此指令失效。显示字符时要先输入显示字符地址,即告诉模块在哪里显示字符,如图2-34是1602 LCD的内部显示地址。
图2-34 1602 LCD内部显示地址
例如,第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1,所以,实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。
在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标自动右移,无须人工干预。每次输入指令前都要判断液晶模块是否处于忙碌状态。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形。这些字符包括阿拉伯数字、英文字母的大小写、常用的符号、日文假名等,每一个字符都有一个固定的代码,例如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,就能看到字母“A”。
(4)1602 LCD的一般初始化(复位)过程 1602 LCD的初始化过程如图2-35所示,详细过程如下。
图2-35 1602 LCD初始化过程
延时15ms。
写指令38H(不检测忙信号)。
延时5ms。
写指令38H(不检测忙信号)。
延时5ms。
写指令38H(不检测忙信号)。
以后每次写指令、读/写数据操作均需要检测忙信号。
写指令38H:显示模式设置。
写指令08H:显示关闭。
写指令01H:显示清屏。
写指令06H:显示光标移动设置。
写指令0CH:显示开及光标设置。
2.9.3 硬件设计
1602 LCD与ATmega128单片机的硬件连接如图2-36所示,其中,1602 LCD的AD0~AD7与ATmega128单片机的端口A相连,控制端口RS、RW、EC分别与端口F的PF1、PF2、PF3相连。
图2-36 1602 LCD与ATmega128接线原理图
2.9.4 程序设计
以下为1602 LCD的显示程序。程序使用ICCAVR环境编译,硬件调试通过。程序使1602 LCD显示两行字符:第一行显示“welcome to”,第二行显示“qing dao”。
目的:1602液晶显示。
功能:1602液晶显示。
时钟频率:内部1MHz。
编译环境:ICC-AVR6.31。
使用硬件:1602液晶。
结果:1602液晶第一行显示“welcome to”,第二行显示“qing dao”。
操作要求:调节液晶对比度旋钮R28使液晶达到最佳显示。
程序清单如下:
(1)头文件部分
# include< string.h> # include< stdio.h> # include< delay.h> # include< iom128v.h>
(2)宏定义部分
# define uchar unsigned char # define uint unsigned int # define RS_CLR PORTF &= ~(1< < PF1) //RS置低 # define RS_SET PORTF 1= (1< < PF1) //RS置高 # define RS0CLR PORTF&= ~(1< < PF2) //RW置低 # define RW_SET PORTF 1= (1< < PF2) //RW置高 # define EN_CLR PORTF&= ~(1< < PF3) //E置低 # define EN_SET PORTF|~(1< < PF3) //E置高 # define Datd - IO PORTA //液晶数据口 # define Data_DDR DDRA //数据口方向寄存器 # define D_LE0 PORTD&= ~(1< < PD4) //数码管段控制位为0,锁存端口数据 # define D_LE1 PORTAD|= (1< < PD4) //数码管段控制位为 1,锁存器输出与端口一致 # define W_LE0 PORTD &= ~(1< < PD5) //数码管位控制位为 0 # define W_LE1 PORTD|= (1< < PD5) //数码管位控制位为 1
(3)微秒级延时函数
void delay_us(unsigned int n) { if(n= = 0) { return; } while(- - n); }
(4)毫秒级延时函数
void delay_ms(unsigned char i) { unsigned char a,b; for (a= 1;a< i;a+ + ) { for (b= 1;b;b+ + ) { ; } } }
(5)显示屏命令写入函数
void LCD_write_com(unsigned char com) RS_CLR; RW_CLR; EN_SET; PORTB= com; delay_us(5); EN_CLR; }
(6)显示屏数据写入函数
void LCD_write_data(unsigned char data) { RS_SET; RW_CLR; EN_SET; PORTB= data; DELAY_US(5); EN_CLR; }
(7)显示屏清空显示函数
void LCD_cear(void) { LCD_write_com(0x01); Delay_ms(5);}
(8)显示屏字符串入函数
void LCD_write_atr(unsigned,char x,unsigned char y,unsigned char*s) { if(y= = 0) { LCD_write_com(0x80+ X); } else { LCD_write_com(0xC0+ x); } while(*s) { LCD_write_data(*s) s+ + ; } }
(9)显示屏单字符写入函数
void LCD_write_char(unsigned char x,unsigned char y,unsigned char data) { if(y= = 0) { LCD_write_com(0x80+ x); } else { LCD_write_com(0Xc0+ x); } LCD_write_data(darta); }
(10)显示屏初始化函数
void LCD_init(void) { DDRA= 0xAFF; //I/O口方向设置 DDRA|= (1< < PA5)|(1< < PA6) (1< < PA7); LCD_write_com(0x38); //显示模式设置 delay - nms(5); LCD_write_com(0x08); //显示关闭 delay_nms(5); LCD_write_com(0x01); //显示清屏 delay_nms(5); LCD_write_com(0x06); //显示光标移动设置 delay_nms(5); LCD_write_com(0x0C); //显示开及光标设置 delay_nms(5); }
(11)初始化子程序
void system_inie() { Data_IO= 0xFF; //电平设置 Data_DDR= 0xFF; //方向输出 PORTF= 0xFF; //电平设置 PORTD= 0xFF; //方向输出 DDRD= 0xFF; D_LE1; //关闭数码管,以免显示乱码 W_LDE1; Data_IO= 0xFF; //关闭数码管 W_LE0; }
(12)主函数
void main(void) { unsingned char i; unsigned char *p; system_initr(); //系统初始化,设置 I/O口属性 delay_nms(100); //延时 100ms LCD_init(); //液晶参数初始化设置 while(1) { i= 1; P= qing dao; //字符串输出显示 LCD_clear(); LCD_write_str(0,0,welcme to); delayt_nms(250); while(*p) { LCD_write_char(i,1,*p); //单个字符输出显示 i+ + ; p+ + ; delay_nms(250); //延时 250ms } Delay_nms(250); } }