51驱动LCD1602
1602 采用标准的 16 脚接口,其中:
第 1 脚:VSS 为地电源
第 2 脚:VDD 接 5V 正电源
第 3 脚:V0 为液晶显示器对比度调整端,接正电源时对比度最弱,接地
电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一
个 10K 的电位器调整对比度
第 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指
令寄存器。
第5脚:RW 为读写信号线,高电平时进行读操作,低电平时进行写操作。
当 RS 和 RW 共同为低电平时可以写入指令或者显示地址,当 RS 为低电
平 RW 为高电平时可以读忙信号,当 RS 为高电平 RW 为低电平时可以写
入数据。
第 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执
行命令
第 7~14 脚:D0~D7 为 8 位双向数据线。
第 15~16 脚:空脚
1602 液晶模块内部的字符发生存储器(CGROM)已经存储了 160 个不
同的点阵字符图形,如表 1 所示,这些字符有:阿拉伯数字、英文字母
的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代
码,比如大写的英文字母“A”的代码是 01000001B(41H),显示时模
块把地址 41H 中的点阵字符图形显示出来,我们就能看到字母“A
1602驱动最核心包含三个函数
1.读状态
其中第七位为设备忙状态,若为1,则暂时不能像设备内部写入数据,为0才能写入
0-6位为当前LCD的数据指针
2.写数据
3.写指令
LCD1602一共有13条命令,他的命令都有以一个基础命令+配置来形成
比如显示命令的基础是0x80,低三位分别是显示开关,光标开关,光标闪烁开关,所以,只需要记住基础命令,使用的时候根据配置加上去写入到LCD就可以了
具体命令如下
1602的内部数据显示第一行0x0-0x27,其中只有0x0-0x0f可以展现(在屏幕不移动的情况下),剩下的,是为了设置为屏幕移动的时候,造成刷屏效果而存在的
话不多说,上代码
#ifndef __COMMON_H_ #define __COMMON_H_ #include <reg52.h> #define u8 unsigned char #define u16 unsigned short #define u32 unsigned int #define s8 signed char #define s16 signed short #define s32 signed int #define p00 P0^0 #define p01 P0^1 #define p02 P0^2 #define p03 P0^3 #define p04 P0^4 #define p05 P0^5 #define p06 P0^6 #define p07 P0^7 #define p10 P1^0 #define p11 P1^1 #define p12 P1^2 #define p13 P1^3 #define p14 P1^4 #define p15 P1^5 #define p16 P1^6 #define p17 P1^7 #define p20 P2^0 #define p21 P2^1 #define p22 P2^2 #define p23 P2^3 #define p24 P2^4 #define p25 P2^5 #define p26 P2^6 #define p27 P2^7 #define p30 P3^0 #define p31 P3^1 #define p32 P3^2 #define p33 P3^3 #define p34 P3^4 #define p35 P3^5 #define p36 P3^6 #define p37 P3^7 #define XTAL 11059200 #endif
#ifndef __LCD1602_H_ #define __LCD1602_H_ #include "common.h" #include "delay.h" # include <intrins.h> //lcd1602指令集定义 //1602基础显示模式 #define LCD1602_DEFAULT_SHOW_MODE 0X38 #define LCD1602_SHOW_SET_BASE 0X08 //BIT2 开显示˸1 关显示0 //BIT1 显示光标1 不显示光标0 //BIT0 光标闪烁1 光标不闪烁0 #define LCD1602_SHOW_POINT_SET_BASE 0X04 //BIT1 读写后指正+1 1 读写后指针-1 0 //BIT0 屏幕自动移动1 屏幕不自动移动0 #define LCD1602_SHOW_CLEAR 0X01 #define LCD1602_POINT_ZERO 0X02 #define LCD1602_SET_DATA_POINT 0X80 //0X0-0X27 第一行写入地址 //0x40-0x67 第二行写入地址 void Lcd1602Init(void); void Lcd1602Clear(void); void Lcd1602ShowChar(u8 x,u8 y,u8 dat); void Lcd1602SetPos(u8 x,u8 y); void Lcd1602ShowStr(u8 x,u8 y,u8* str); #endif
#include "lcd1602.h" sbit LCD1602_RS_PIN = p07; sbit LCD1602_RW_PIN = p06; sbit LCD1602_EN_PIN = p05; #define LCD1602_DATA P2 #define LCD_RS_CMD LCD1602_RS_PIN = 0 #define LCD_RS_DAT LCD1602_RS_PIN = 1 #define LCD_RW_WRITE LCD1602_RW_PIN = 0 #define LCD_RW_READ LCD1602_RW_PIN = 1 #define LCD_EN_HIGH LCD1602_EN_PIN = 1 #define LCD_EN_LOW LCD1602_EN_PIN = 0 static void delay (int m) { unsigned char i,j; for (i=0;i<m;i++) for (j=0;j<253;j++); } static bit Lcd1602ReadStatus(void) { bit result; LCD_RS_CMD; LCD_RW_READ; LCD_EN_HIGH; _nop_(); _nop_(); _nop_(); _nop_(); result = (bit)(LCD1602_DATA&0x80); LCD_EN_LOW; return result; } static void Lcd1602WriteCommand(u8 command) { while(Lcd1602ReadStatus()); LCD_RS_CMD; LCD_RW_WRITE; LCD_EN_LOW; _nop_(); _nop_(); LCD1602_DATA = command; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EN_HIGH; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EN_LOW; } static void Lcd1602WriteData(u8 dat) { while(Lcd1602ReadStatus()); LCD_RS_DAT; LCD_RW_WRITE; LCD_EN_LOW; _nop_(); _nop_(); LCD1602_DATA = dat; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EN_HIGH; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EN_LOW; } void Lcd1602SetPos(u8 x,u8 y) { u8 pos = 0; if(y)pos = 0x80+0x40+x; else pos = 0x80+x; Lcd1602WriteCommand(pos); } void Lcd1602ShowChar(u8 x,u8 y,u8 dat) { Lcd1602SetPos(x,y); Lcd1602WriteData(dat); } void Lcd1602Clear(void) { Lcd1602WriteCommand(LCD1602_SHOW_CLEAR); } void Lcd1602Init(void) { Lcd1602WriteCommand (LCD1602_DEFAULT_SHOW_MODE); delay(1); Lcd1602WriteCommand (0x0c);//开显示,无光标 delay (1); Lcd1602WriteCommand (0x06);//屏幕自动+1 不移动 delay (1); Lcd1602WriteCommand (0x01);//清屏 delay (1); } void Lcd1602ShowStr(u8 x,u8 y,u8* str) { u8 i = 0; Lcd1602SetPos(x,y); for(i = 0; i < 16-x;i++) { if(*(str+i) != '\0') Lcd1602WriteData(*(str+i)); else break; } }