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

2009-4-10 21:57 8048 10 10 分类: MCU/ 嵌入式

51单片机1602液晶驱动程序(一)总线方式<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


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


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


英文名称叫“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 说明书


 


从上面的两个说明书可以看到1516管脚是反着的,1516管脚对应LCM的背光电源地,如果LCM本身是不带背光的话,这两个管脚是没用的。如果LCM是带背光的话,要注意这两个管脚的连接,具体先测试一下,确定哪个是电源哪个是地。


基本操作时序:


1 读状态:输入:RS=L,RW=H,E=H 输出:D0D7=状态字


2 写指令:输入:RS=L,RW=L,D0D7=指令码,E=高脉冲 输出:无


3 读数据:输入:RS=H,RW=H,E=H 输出:D0D7=数据


4 写数据:输入:RS=H,RW=L,D0D7=数据,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>”即可使用其中定义的宏来访问绝对地址,包括:
CBYTEXBYTEPWORDDBYTECWORDXWORDPBYTEDWORD


<absacc.h>这个文件在用到总线方式时必须用到。


 



86000a79-cff6-4ed5-8d5b-9ba0fad42ee2.JPG 


共包含4个文件。在主程序中调用相应显示函数。


 


//******************** main.c***********************************


#include <lcd1602b.h>


#include <reg52.h>


code char capital[]="DFB Laser";


 


main()


{


……


LcdReset();                                                         //LCD初始化


       LcdDisplayString(3,0,capital);                      //LCD上显示"DFB Laser"


    ……


}

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

coyoo 2014-4-9 12:11

群里“炸凉”是你,此问题还是在群里讨论较好,这里回复无法贴图。

用户1739054 2014-4-9 11:40

我在慢慢解决,我现在用quartus11.0,用quartus_stp -t my_jtag.tcl时报错了Error:invalid command name "quartus_stp"这是啥原因。

coyoo 2014-4-9 11:08

我觉得这应该都是小问题;比如signaltap和当前的sof不匹配啊,或者vj打开fpga时提供的编号不对等

用户1739054 2014-4-9 10:30

单链两片fpga现在通过跳线变成一个fpga,通过quartus下载程序(只下载一片)后,竟然又提示找不到vjtag了。恢复到两片调试还是正确的,这是怎么回事?通过auto detect 他只能找到一片。sigtap不能使用,提示的错误和两片时其中一片不下载程序是一样的

用户1739054 2014-4-9 10:06

我现在改成单链单fpga之后竟然又找不到vjtag了,也没有用sigtap。

coyoo 2014-3-27 11:59

我也感觉似乎纸张质量一般!如果有盗版,我还是会感到挺荣幸滴,呵呵

用户1739054 2014-3-27 11:54

奥,我研究一下。书到了,亚马逊直营的,我同事说怎么像被人盗版了

coyoo 2014-3-27 11:01

我记得好像在哪儿回复过这个问题。带signaltap说明,你使用到了这个GXB,如果不带,说明你们没有用到这个GXB,而Quartus II软件不能像优化掉其它未用逻辑那样将GXB优化掉,所以只好报错

用户1739054 2014-3-27 10:55

今天我遇到一个问题就是我的GXB接口编译带着sigtap就会编译通过但是编译不加sigtap就不会编译通过。会提示这个信息Error: Can't place input pin "RX_in[0]" in Pin_N1 because the pin is not connected to GXB Transceiver logic but the location is GXB Receiver pin.。这是个什么问题

coyoo 2014-3-26 14:36

这个跟单片还是多片没有关系;单片和多片的问题是每次只能打开一片,需要随时注意当前打开的是那片即可。找不到VJ,要查TCL代码到逻辑之间的匹配问题。比如ir_in位宽为2-bit,那么最多可以解码4个指令,如果超过4个指令,那么需要重新修改VJ核的例化参数,比如修改到3-bit,那么最多可以解码8个指令,以此类推。
相关推荐阅读
藤井树 2015-10-12 14:43
印制电路板的抗干扰设计 zz
印制电路板的抗干扰设计     作者:中船重工集团第707所 肖麟芬   摘   要:本文以印制电路板的电磁兼容性为核心,分析了电磁干扰的产生机理...
藤井树 2013-10-22 15:32
2010.5.30 黄草梁上包饺子一日登山活动——摘韭菜篇
        上次桃花节的时候也有野韭菜,那时候的我连草和韭菜叶分不清,才回去的韭菜也不敢吃,哈哈,这次可算真正见识了韭菜,黄草梁也叫韭菜梁,因为满山遍野都是野韭菜而闻名,比较圆比较粗的就是野韭...
藤井树 2013-10-22 15:28
2010.5.30 黄草梁上包饺子一日登山活动——包饺子篇
摘韭菜回来,大家已经忙开了 我也装模作样地“工作着” 哈哈,还不让我包,包饺子是技术活,一定要皮薄馅厚才有资格包,像我这样的只能旁观了 摘的韭菜应该足够了,旁边那个袋子是我摘来带回学校的 ...
藤井树 2013-08-09 15:19
datasheet下载网站整理(查IC芯片手册)【原创】
*************************************************************************         作为电子工程师,芯片的dat...
藤井树 2010-06-04 00:21
陈伟宁王辉一家捐助渠道(北京菲亚特—英菲尼迪)
       王辉的最新消息请关注 http://chenweining.org/       目前事故责任认定已经出来了——陈家全责。        发信人: program (程序), 信区: D...
藤井树 2010-06-01 13:43
2010.5.30 黄草梁上包饺子一日登山活动——美景篇
这天不得不说的是天空,蓝蓝的天空,白白的云    绿油油的山脊  我、洪涛哥哥、huangna妹妹还有她同事小艾走在黄草梁上    在蓝天白云下合影       阳光照过来,景色真美 象鼻山,走不...
EE直播间
更多
我要评论
1
10
关闭 站长推荐上一条 /3 下一条