51单片机1602液晶驱动程序(一)总线方式<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
LCD1602是51单片机的基本应用,其实驱动程序做成模板的话,以后就直接调用就行啦,会省掉很多时间。
LCD1602各个厂家的基本都是兼容的,LCD1601和LCD1604等等驱动程序都是一样的,只是显示的字符数不一样而已。
英文名称叫“LCD Module”,简称“LCM”,中文一般称为“液晶显示模块”。
LCM1601/LCD1601液晶可以显示16x1个字符每行显示16字符;
LCM1602/LCD1602液晶可以显示16x2个字符每行显示16字符;
LCM1604/LCD1604液晶可以显示16x4个字符每行显示16字符。
LCM1602管脚说明
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
长沙太阳人电子有限公司 SMC1602A LCM 使用说明书
北京青云创新科技发展有限公司 LCM1602B 说明书
从上面的两个说明书可以看到15、16管脚是反着的,15、16管脚对应LCM的背光电源地,如果LCM本身是不带背光的话,这两个管脚是没用的。如果LCM是带背光的话,要注意这两个管脚的连接,具体先测试一下,确定哪个是电源哪个是地。
基本操作时序:
1) 读状态:输入:RS=L,RW=H,E=H 输出:D0~D7=状态字
2) 写指令:输入:RS=L,RW=L,D0~D7=指令码,E=高脉冲 输出:无
3) 读数据:输入:RS=H,RW=H,E=H 输出:D0~D7=数据
4) 写数据:输入:RS=H,RW=L,D0~D7=数据,E=高脉冲 输出:无
初始化过程(复位过程):
1)延时15ms
2)写指令38H(不检测忙信号)
3)延时5ms
4)写指令38H(不检测忙信号)
5)延时5ms
6)写指令38H(不检测忙信号)
7)(以后每次写指令、读/写数据操作之前均需检测忙信号)
8)写指令38H:显示模式设置
9)写指令08H:显示关闭
10)写指令01H:显示清屏
11)写指令06H:显示光标移动设置
12)写指令0CH:显示开及光标设置
LCM1602参考连接
LCM1602有两种方式驱动,8051系列总线方式和8051系列模拟口线方式。
1.8051系列总线方式:
LCM1602总线方式C51程序
//********************Lcd1602B.c***********************************
#include <delay.h>
#include <lcd1602b.h>
#include <absacc.h>
/*=======================================================
显示字符串
=======================================================*/
void LcdDisplayString(unsigned char x,unsigned char y, unsigned char *ptr) {
unsigned char i,l=0;
while (ptr[l] >31){l++;}; //
for (i=0;i<l;i++) {
LcdDisplayChar(x++,y,ptr);
if ( x == 16 ){
x = 0; y ^= 1; //异或,第一行的话变第二行,第二行的话变第一行
}
}
}
/*=======================================================
显示光标定位
=======================================================*/
void LocateXY( char posx,char posy) {
unsigned char temp;
temp = posx & 0x<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />0f; //确保只选0~16个格子
posy &= 0x01; //确保不是在第一行就在第二行
if ( posy )temp |= 0x40; //在第二行的时候加40H
temp |= 0x80; //数据指针设置 指令码 80H+ 地址码( 0-27H ,40H-67H)
LcdWriteCommand(temp,1);
}
/*=======================================================
按指定位置显示数出一个字符
=======================================================*/
void LcdDisplayChar(unsigned char x,unsigned char y,unsigned char Wdata) {
LocateXY( x, y ); // 定位显示地址
LcdWriteData( Wdata ); // 写字符
}
/*=======================================================
初始化程序, 必须按照产品资料介绍的初始化过程进行
=======================================================*/
void LcdReset( void ) {
Delayms(400); // 启动时必须的延时,等待lcm进入工作状态
LcdWriteCommand( 0x38, 0); // 显示模式设置(不检测忙信号)
Delayms(15);
LcdWriteCommand( 0x38, 0); // 共三次
Delayms(15);
LcdWriteCommand( 0x38, 0);
Delayms(15);
LcdWriteCommand( 0x38, 1); // 显示模式设置(以后均检测忙信号)
LcdWriteCommand( 0x08, 1); // 显示关闭
LcdWriteCommand( 0x06, 1); // 显示光标移动设置
LcdWriteCommand( 0x0c, 1); // 显示开及光标设置
LcdClear();
}
/*=======================================================
clear
=======================================================*/
void LcdClear(void){
LcdWriteCommand( 0x01, 1); // 显示清屏
}
/*=======================================================
写控制字符子程序: E="1" RS="0" RW="0"
=======================================================*/
void LcdWriteCommand( unsigned char CMD,unsigned char AttribC ) { //AttribC=1检查忙状态,AttribC=0不检查忙状态
if (AttribC) while( Lcd1602StatusPort & Busy ); // 检测忙信号?
//busy=0x80 每次读写操作都要进行读写检测,确保SAT7=0
Lcd1602CmdPort = CMD;
}
/*=======================================================
当前位置写字符子程序: E =1 RS="1" RW="0"
=======================================================*/
void LcdWriteData( char dataW ) {
while( Lcd1602StatusPort & Busy ); //检测忙信号
//busy=0x80 每次读写操作都要进行读写检测,确保SAT7=0
Lcd1602WdataPort = dataW;
精确微秒级延时(详细可以参考我另一篇博文51单片机C51微秒级(ms)精确延时 )
//********************delay.h***********************************
#include <delay.h>
//for crystal 11.0592M
void Delayms(unsigned int n)
{
unsigned int i,j;
for(j=n;j>0;j--)
for(i=112;i>0;i--);
}
//********************lcd1602b.h***********************************
#ifndef __LCD1602B_H__
#define __LCD1602B_H__
#define Lcd1602CmdPort XBYTE[0x8000] //E=1 RS="0" RW="0" //写指令
#define Lcd1602WdataPort XBYTE[0x8100] //E =1 RS="1" RW="0" //写数据
#define Lcd1602StatusPort XBYTE[0x8200] //E=1 RS="0" RW="1" //读状态
#define Busy 0x80 //busy
extern void LcdClear(void);
extern void LcdWriteData( char dataW );
extern void LcdWriteCommand( unsigned char CMD,unsigned char AttribC );
extern void LcdReset( void );
extern void Display( unsigned char dd );
extern void LcdDisplayChar(unsigned char x,unsigned char y,unsigned char Wdata);
extern void LcdDisplayString(unsigned char x,unsigned char y, unsigned char *ptr);
#endif
其中要注意
写指令的地址 0x8000
写数据的地址 0x8100
读状态的地址 0x8200
这三个地址值是根据硬件电路连接确定的。
//******************** absacc.h***********************************
#ifndef __ABSACC_H__
#define __ABSACC_H__
#define CBYTE ((unsigned char volatile code *) 0)
#define DBYTE ((unsigned char volatile data *) 0)
#define PBYTE ((unsigned char volatile pdata *) 0)
#define XBYTE ((unsigned char volatile xdata *) 0)
#define CWORD ((unsigned int volatile code *) 0)
#define DWORD ((unsigned int volatile data *) 0)
#define PWORD ((unsigned int volatile pdata *) 0)
#define XWORD ((unsigned int volatile xdata *) 0)
#ifdef __CX51__
#define FVAR(object, addr) (*((object volatile far *) (addr)))
#define FARRAY(object, base) ((object volatile far *) (base))
#define FCVAR(object, addr) (*((object const far *) (addr)))
#define FCARRAY(object, base) ((object const far *) (base))
#else
#define FVAR(object, addr) (*((object volatile far *) ((addr)+0x10000L)))
#define FCVAR(object, addr) (*((object const far *) ((addr)+0x810000L)))
#define FARRAY(object, base) ((object volatile far *) ((base)+0x10000L))
#define FCARRAY(object, base) ((object const far *) ((base)+0x810000L))
#endif
#endif
在程序中,用“#include<absacc.h>”即可使用其中定义的宏来访问绝对地址,包括:
CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD
<absacc.h>这个文件在用到总线方式时必须用到。
共包含4个文件。在主程序中调用相应显示函数。
//******************** main.c***********************************
#include <lcd1602b.h>
#include <reg52.h>
code char capital[]="DFB Laser";
main()
{
……
LcdReset(); //LCD初始化
LcdDisplayString(3,0,capital); //LCD上显示"DFB Laser"
……
}
coyoo 2014-4-9 12:11
用户1739054 2014-4-9 11:40
coyoo 2014-4-9 11:08
用户1739054 2014-4-9 10:30
用户1739054 2014-4-9 10:06
coyoo 2014-3-27 11:59
用户1739054 2014-3-27 11:54
coyoo 2014-3-27 11:01
用户1739054 2014-3-27 10:55
coyoo 2014-3-26 14:36