LCD1602工作原理介绍 |
您所在的位置:网站首页 › 主要技术参数拼音 › LCD1602工作原理介绍 |
LCD1602液晶显示屏简介
LCD1602(Liquid Crystal Display)是一种工业字符型液晶,能够同时显示16×02即32字符(16列两行),LCD1602主要用来显示数字、字母、图形以及少量自定义字符。可以显示2行16个字符,拥有16个引脚,其中8位数据总线D0-D7,和RS、R/W、EN三个控制端口,工作电压为5V,并且带有字符对比度调节V0和背光源AK。 ![]() 引脚1(VSS/GND):地引脚 引脚2(VDD/VCC):电源引脚 引脚3(VL):液晶显示器对比度引脚,接正电源时对比度最弱,接地时对比度最高,使用时可以通过外接一个电位器调整其对比度。 引脚4(RS):寄存器选择脚,高电平时选择数据寄存器、低电平时选择指令寄存器。 引脚5(R/W):读(read)/写(write)信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或显示地址;当RS为低电平,R/W为高电平时,可以读忙信号;当RS为高电平,R/W为低电平时,可以写入数据。 引脚6(E):使能端,当E端由高电平跳变为低电平时,液晶模块执行命令。 引脚7-14(D0~D7): 8位双向数据线 用于单片机向1602写入数据和从1602读取数据 引脚15(BLA):背光源正极 引脚16(BLK):背光源负极 LCD1602引脚接线(51单片机)虽然看到LCD1602的引脚很多,但是总体分下来其实只需要分成三个部分记忆去接线就好了。 第一部分(电源、接地):这里会分为两组,一组是VDD/GND组,主要给模块供电、另一组是BLA/BLK组,主要给背光源供电。由于VL引脚接地,也将它放在此部分记忆。 注:两组我的写法都是以接5V电源/接地的顺序写的,当然也可以按着引脚说明部分自己注意甄别。 第二部分(IO口):也就是引脚7-14(D0-D7)由于他是8位双向数据线,所以按照顺序依次接51单片机P0^0引脚-P0^7引脚 第三部分(信号线):引脚RS(数据命令选择端)、R/W(读写选择端)、E(使能信号)可以随意选择其他IO口接线,这里以我自己写的代码所定义的引脚为例(C代码): LCD1602,总共显示为16行2列,对应着32个RAM地址,在使用的时候,需要在哪个位置显示,就写入对应的RAM地址,然后再写入需要的字符,对应就会显示该字符。 下图是LCD1602的内部显示地址 一共32个地址,对应2行16列 如果我要在第二行第一个位置显示字符,它的地址是 40H,那么是否直接写入 40H 就可以将光标定位在第二行第 一个字符的位置呢? 答:这样不行,因为写入显示地址时要求最高位 D7 恒定为高电平 1 所以实 际写入的数据应该是 01000000B(40H) +10000000B(80H)=11000000B(C0H)。 那要显示什么字符呢就需要结课ASCII码表 如上图所示,需要写入哪个字符,就直接设置对应进制码就可以了,比如数字1,代码是0011 0001与ASCII码一致。也就是表中的ASCII码字符的地址和实际的ASCII码字符是一样的。 读时序、写时序及数序参数以下为读时序和写时序的图以及数序参数。 读时序: 写时序: 数序参数: 首先我们先来观察写时序的图,通过时序图来确定代码 在前面引脚功能部分有提到RS引脚为寄存器选择脚,高电平(1)时为选择数据寄存器、低电平(0)时为选择指令寄存器。我们知道液晶显示模块需要先有告诉在显示屏哪个地址显示字符后,再做显示字符操作,选择指令寄存器就是告知模块指令或地址、选择数据寄存器则是写入数据操作。不过要结合R/W来看。 告知模块指令或地址时的写时序中一开始需要让RS = 0,继续观察写时序图我们会发现E一开始也是低电平,R/W一开始可高可低,但是根据后续变化来看,主要实现操作的电平为低电平,所以干脆直接在写时序里全程低电平,即: RS = 0; R/W = 0; EN = 0;//在定义时,将E接口命名成了EN 如图,我们需要延时tsp1的时间为传输数据做准备,而后E会给到一个上升沿,这个时候指令就开始写入LCD中,此刻根据数序参数给到一定的延时后,将E置低电平。 在准备传输数据阶段期间,其实已经开始将指令数据送到数据口D0~D7,所以综合以上时序的解析,代码如下: 注:这个是一个自己写的函数,在主程序中调用,其中char cmd传进来的是需要显示字符的地址,check_busy();这个是读忙的函数,后续会提到,databuffer是之前定义的P0口,其中用到_nop_();做延时作用,它是一个空函数,运行它时大概需要1.085微妙,足够满足数序参数的需求。不过值得注意的是_nop_();需要加头文件#include "intrins.h"。 在写入数据时的写时序,只需要RS需要为高电平,其他和告知模块指令或地址时一致,代码如下: 我们可以根据一下步骤进行书写LCD1602的初始化 LCD1602 初始化过程(8bit)(1)延时 15ms (2)写指令 38H(不检测忙信号) (3)延时 5ms (4)以后每次写指令,读/写数据操作均需要检测忙信号 (5)写指令 38H:显示模式设置 (6)写指令 08H:显示关闭 (7)写指令 01H:显示清屏 (8)写指令 06H:显示光标移动设置 (9)写指令 0CH:显示开及光标设置 LCD1602 初始化过程(4bit)(01)延时 50ms (02)发送 0x03(4bit)(rs=0,rw=0) (03)延时 4.5ms (04)发送 0x03(4bit)(rs=0,rw=0) (05)延时 4.5ms (06)发送 0x03(4bit)(rs=0,rw=0) (07)延时 150μs (08)发送 0x02(4bit)(rs=0,rw=0) (09)写指令 28H(8bit) (10)写指令 0CH(8bit) (11)写指令 01H(8bit) (12)延时 2ms(8bit) (13)写指令 06H(8bit) 因为我操作的是8bit的情况,如下图代码实现: LCD1602一共有11条指令,今天主要说读忙指令 1602液晶模块的读写操作,屏幕和光标的操作都是通过指令来实现的。(1为高电平,0为低电平),操作指令整理如下图: BF:忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平表示不忙 读忙指令编码可以知道要RS=0,R/W=1,这时需要观察读时序的图来判断E的状态,如下图 依旧是我们需要延时tsp1的时间,并等待E提供一个上升沿,并延时一段时间,只是在读数据时是在E=1之后,所以获取数据的位置需要改变,其他E的状态变化和写时序没太大区别,代码如下 这时我们需要做一个循环判断,来确定指令是不是处于忙状态,前面有提到当BF = 1时为忙状态,而它位于DB7口,其他IO口无所谓,所以可以定义一个tmp=0x80,databuffer=0x80,这样如上图所示,用databuffer给tmp赋值,当databuffer的P0^7口为0或1时,做while(tmp & 0x80)的判断。完整代码如下: 这时,我想要输出一个字符'C'的话,主函数如下写即可。 当然,如果想输出一个字符串需要再做一个函数,如下图: 注:其中row和col做的是在LCD1602的第几行显示的判断,row利用switch做判断,col做逻辑选择。这里解析一下0x80+col和0x80+0x40+col的操作为什么可以确定是第几行,0x80在前面已经有聊到过为什么需要加,写入显示地址时要求最高位 D7 恒定为高电平 1 。而第一行的第一个地址是00,也就是0x00,换算为十进制为0,而第二行地址为40,即0x40,换算为十进制则是64,但是由于不太美观且和上面不一致,不如写成0x80+0x40+0这样,就可以以形参的形式传递,具有比较好的观感。最后一个则是传递字符串的。 OK,今天的介绍就到这里吧,以下为完整代码 完整代码 #include "reg52.h" #include "intrins.h" /* RS -- P1.0 RW -- P1.1 E -- P1.4 */ #define databuffer P0 //定义8位数据线,Po端口组 sbit RS = P1^0; sbit RW = P1^1; sbit EN = P1^4; void check_busy() { char tmp = 0x80; databuffer = 0x80; while(tmp & 0x80){//1000 0000 RS = 0; RW = 1; EN = 0; _nop_(); EN = 1; _nop_(); _nop_(); tmp = databuffer; EN = 0; _nop_(); } } void Write_Cmd_Func(char cmd) { check_busy(); RS = 0; RW = 0; EN = 0; _nop_(); databuffer = cmd; _nop_(); EN = 1; _nop_(); _nop_(); EN = 0; _nop_(); } void Write_Data_Func(char dataShow) { check_busy(); RS = 1; RW = 0; EN = 0; _nop_(); databuffer = dataShow; _nop_(); EN = 1; _nop_(); _nop_(); EN = 0; _nop_(); } void Delay15ms() //@11.0592MHz { unsigned char i, j; i = 27; j = 226; do { while (--j); } while (--i); } void Delay5ms() //@11.0592MHz { unsigned char i, j; i = 9; j = 244; do { while (--j); } while (--i); } void LCD1602_INIT() { //(1)延时 15ms Delay15ms(); //(2)写指令 38H(不检测忙信号) Write_Cmd_Func(0x38); //(3)延时 5ms Delay5ms(); //(4)以后每次写指令,读/写数据操作均需要检测忙信号 //(5)写指令 38H:显示模式设置 Write_Cmd_Func(0x38); //(6)写指令 08H:显示关闭 Write_Cmd_Func(0x08); //(7)写指令 01H:显示清屏 Write_Cmd_Func(0x01); //(8)写指令 06H:显示光标移动设置 Write_Cmd_Func(0x06); //(9)写指令 0CH:显示开及光标设置} Write_Cmd_Func(0x0c); } void LCD1602_showLine(char row, char col, char *string) { switch(row){ case 1: Write_Cmd_Func(0x80+col); while(*string){ Write_Data_Func(*string); string++; } break; case 2: Write_Cmd_Func(0x80+0x40+col); while(*string){ Write_Data_Func(*string); string++; } break; } } void main() { char position = 0x80 + 0x05; //char dataShow = 'C'; LCD1602_INIT(); LCD1602_showLine(1,5,"NO.1"); LCD1602_showLine(2,0,"clc handsome"); } |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |