新闻  |   论坛  |   博客  |   在线研讨会
51单片机1602液晶驱动程序(一)总线方式
0750long | 2009-04-11 09:14:39    阅读:5651   发布文章

51单片机1602液晶驱动程序(一)总线方式

LCD1602是51单片机的基本应用,其实驱动程序做成模板的话,以后就直接调用就行啦,会省掉很多时间。

LCD1602各个厂家的基本都是兼容的,LCD1601和LCD1604等等驱动程序都是一样的,只是显示的字符数不一样而已。

英文名称叫“LCD Module”,简称“LCM”,中文一般称为“液晶显示模块”。

LCM1601/LCD1601液晶可以显示16x1个字符每行显示16字符;

LCM1602/LCD1602液晶可以显示16x2个字符每行显示16字符;

LCM1604/LCD1604液晶可以显示16x4个字符每行显示16字符。

 

LCM1602管脚说明

 

点击看大图

长沙太阳人电子有限公司 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[i]);

              if ( x == 16 ){

                     x = 0; y ^= 1; //异或,第一行的话变第二行,第二行的话变第一行

              }

       }

}

 

/*=======================================================

 显示光标定位

=======================================================*/

void LocateXY( char posx,char posy) {

 

unsigned char temp;

 

       temp = posx & 0x0f;             //确保只选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"

    ……

}

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客