完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
DS1602液晶显示 LCM1602是最常见的点阵字符型液晶显示模块,由液晶板、控制器HD44780、驱动器HD44100及若干电阻电容组成。 1602 液晶,从它的名字我们就可以看出它的显示容量,就是可以显示 2 行,每行 16 个字符的液晶,即其液晶板上分2行,每行排列着16个5×7的点阵,专门用于显示字母、数字以及符号。 /// 1602实物图: 0它可与8位或4位微处理器连接;内建CGROM可提供160种工业标准字符,包括全部大小写字母、阿拉伯数字、日文假名以及32个特殊字符或符号的显示;内建CGRAM可根据用户需要,由用户自行设计定义8个字符或符号; 先了解以下几个概念:CGROM、CGRAM、DDRAM和AC CGROM是只读字符发生器,存放192个字符的点阵数据,每个字符都有一个唯一的代码,在0x20~0x7f区间代码值就是该字符的ASCII码,图12-9为LCM1602的内置字符集。 CGRAM是自定义字符发生器,可用于存放用户自定义字符的点阵,只有64个字节最多能定义8个字符,这8个字符也有对应的代码,0x00对应第一个自定义字符,0x07对应最后一个自定义字符,0x08~0x0f与0x00~0x07指向相同的字符。 DDRAM是显示存储器,有80个字节,内部存放的是显示内容的代码。 AC是DDRAM和CGRAM共用的地址指针计数器,另外AC也作为光标和闪烁位置指针。 1602 液晶一共 16 个引脚: 左起为1脚,各引脚功能如下: 1脚:VSS为模块电源地,接地; 2脚:VDD为模块电源正,接+5V; 3脚:VEE为对比度调节引脚,接电源正时对比度最差,接电源地时对比度最高,通常接一个10K电位器(滑动变阻器)到地(可手动调节)调节显示对比度; 4脚:RS为寄存器选择位,输入脚,“1”数据寄存器,“0”命令寄存器; 5脚:RW为读写操作选择位,输入脚,“1”读操作,“0”写操作; 6脚:E为使能信号,输入脚,读操作时上升沿有效,写操作时下降沿有效; 7~14脚:DB0~DB7双向数据线,DB7还做忙闲标志位使用,4线工作方式下仅DB4~DB7有效; 15脚:BL1背光电源正,接+5V; 16脚:BL2背光电源地,接地。 重要引脚ps: ( 4 脚是数据命令选择端。对于液晶,有时候我们要发送一些命令,让它实现我们想要的一些状态,有时候我们要发给它一些数据,让它显示出来,液晶就通过这个引脚来判断接收到的是命令还是数据,这个引脚我们接到了 ADDR0 上,通过跳线帽和 P1.0 连接在一起。读手册看到这个引脚描述里:数据/命令选择端,而后跟了括号(H/L),他的意思就是当这个引脚是 H(High)高电平的时候,是数据,当这个引脚是 L(Low)低电平的时候,是命令。 5 脚和 4 脚用法类似,功能是读写选择端。我们既可以写给液晶数据或者命令,也可以读取液晶内部的数据或状态,就是控制这个引脚。因为液晶本身内部有 RAM,实际上我们送给液晶的命令或者数据,液晶需要先保存在缓存里,然后再写到内部的寄存器或者 RAM中,这个就需要一定的时间。所以我们进行读写操作之前,首先要读一下液晶当前状态,是不是在“忙”,如果不忙,我们可以读写数据,如果在“忙”,我们就需要等待液晶忙完了,再进行操作。读状态是常用的,大家了解这个功能即可。这个引脚我们接到了 ADDR1 上,通过跳线帽和 P1.1 连接在一起。 6 脚是使能信号,很关键,液晶的读写命令和数据,都要靠它才能正常读写,我们后边详细讲这个引脚怎么用。这个引脚我们通过跳线帽接到了 ENLCD 上,这个位置的跳线是为了和另外一个 12864 液晶的切换使用而设计的。 7 到 14 引脚就是 8 个数据引脚了,我们就是通过这 8 个引脚读写数据和命令的。 ) 、、、、、、、、、、、、、、、、 1602 液晶的读写时序介绍: 第一行的地址是 0x00H 到 0x27(40个,0x00-0x0f有16个,依此类推,共16+16+8=40),第二行的地址从 0x40 到 0x67,其中第一行 0x00 到 0x0F是与液晶上第一行 16 个字符显示位置相对应的,第二行 0x40 到 0x4F 是与第二行 16 个字符显示位置相对应的。而每行都多出来一部分,是为了显示移动字幕设置的。 1602 字符液晶是显示字符的,因此它跟 ASCII 字符表是对应的。比如我们给 0x00 这个地址写一个‘a’,也就是十进制的 97,液晶的最左上方的那个小块就会显示一个字母 a。液晶内部有个数据指针,它指向哪里,我们写的那个数据就会送到相应的那个地址里。 液晶有一个状态字字节,我们通过读取这个状态字的内容,就可以知道 1602 液晶的一些内部情况,如表 12-5 所示。 这个状态字节有 8 个位,最高位表示了当前液晶是不是“忙”,如果这个位是 1 表示液晶正“忙”,禁止我们读写数据或者命令,如果是 0,则可以进行读写。 读状态的判忙语句: void LcdWaitReady() { unsigned char sta; LCD1602_DB = 0xFF; LCD1602_RS = 0; //0 为写命令 1为写数据 LCD1602_RW = 1; //1 为读 0为写 do { LCD1602_E = 1; sta = LCD1602_DB; //读取状态字 LCD1602_E = 0; } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止 } 为什么要判断忙闲? 因为流水灯、数码管、点阵、 1602 液晶都用到了 P0 口总线,我们读完了液晶状态继续保持 LCD1602_E 是高电平的话, 1602 液晶会继续输出它的状态值,输出的这个值会占据了 P0 总线,干扰到流水灯数码管等其它外设,所以我们读完了状态,通常要把这个引脚拉低来释放总线。 读数据: RS=H, R/W=L, E=H。 写指令: RS=L, R/W=L, D0~D7=指令码, E=高脉冲。 /* 向 LCD1602 液晶写入一字节命令, cmd-待写入命令值 */ void LcdWriteCmd(unsigned char cmd) { LcdWaitReady(); LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_DB = cmd; LCD1602_E = 1; LCD1602_E = 0; } 写数据: RS=H, R/W=L, D0~D7=数据, E=高脉冲。 /* 向 LCD1602 液晶写入一字节数据, dat-待写入数据值 */ void LcdWriteDat(unsigned char dat) { LcdWaitReady(); LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_DB = dat; LCD1602_E = 1; LCD1602_E = 0; } ps: E=高脉冲这个问题要解释一下。这个指令一共有 4 条语句,其中前三条语句顺序无所谓,但是 E=高脉冲这一句很关键。实际上流程是这样的:因为我们现在是写数据,所以我们首先要保证我们的 E 引脚是低电平状态,而前三句不管我们怎么写, 1602 液晶只要没有接收到 E 引脚的使能控制,它都不会来读总线上的信号的。当通过前三句准备好数据之后, E 使能引脚从低电平到高电平变化,然后 E 使能引脚再从高电平到低电平出现一个下降沿,1602 液晶内部一旦检测到这个下降沿后,并且检测RS=L, R/W=L,就马上来读取 D0~D7的数据,完成单片机写1602指令过程。归纳总结我们写了个E=高脉冲,意思就是: E 使能引脚先从低拉高,再从高拉低,形成一个高脉冲。 而读状态和读命令都是只需要E=H即可。 即读操作时上升沿有效,写操作时下降沿有效。 1602 液晶简单实例 #include #define LCD1602_DB P0 ***it LCD1602_RS = P1^0; ***it LCD1602_RW = P1^1; ***it LCD1602_E = P1^5; void InitLcd1602(); void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str); void main() { unsigned char str[] = "Kingst Studio"; InitLcd1602(); LcdShowStr(2, 0, str); LcdShowStr(0, 1, "Welcome to KST51"); while (1); } /* 等待液晶准备好 */ void LcdWaitReady() { unsigned char sta; LCD1602_DB = 0xFF; LCD1602_RS = 0; LCD1602_RW = 1; do { LCD1602_E = 1; sta = LCD1602_DB; //读取状态字 LCD1602_E = 0; } while (sta & 0x80); //bit7 等于 1 表示液晶正忙,重复检测直到其等于 0 为止 } /* 向 LCD1602 液晶写入一字节命令, cmd-待写入命令值 */ void LcdWriteCmd(unsigned char cmd) { LcdWaitReady(); LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_DB = cmd; LCD1602_E = 1; LCD1602_E = 0; } /* 向 LCD1602 液晶写入一字节数据, dat-待写入数据值 */ void LcdWriteDat(unsigned char dat) { LcdWaitReady(); LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_DB = dat; LCD1602_E = 1; LCD1602_E = 0; } /* 设置显示 RAM 起始地址,亦即光标位置, (x,y)-对应屏幕上的字符坐标 */ void LcdSetCursor(unsigned char x, unsigned char y) { unsigned char addr; if (y == 0) //由输入的屏幕坐标计算显示 RAM 的地址 addr = 0x00 + x; //第一行字符地址从 0x00 起始 else addr = 0x40 + x; //第二行字符地址从 0x40 起始 LcdWriteCmd(addr | 0x80); //设置 RAM 地址 } /* 在液晶上显示字符串, (x,y)-对应屏幕上的起始坐标, str-字符串指针 */ void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str) { LcdSetCursor(x, y); //设置起始地址 while (*str != ' |