新闻  |   论坛  |   博客  |   在线研讨会
wang1jin带您DIY电子时钟(连载2) LCD模块程序编写
0750long | 2009-07-10 08:39:30    阅读:1784   发布文章

 

 

 

 
 
在连载1中给大家介绍的是整体的一些设计和规划...在连载2中我就带大家一起来完成一个LCD1602的函数.
 
为什么要在第一时间来介绍这个呢,呵呵.因为它是显示数据的.如果没有先把它搞好,你就算把别的完成了,也看不到数据和信息.这就是为什么我要第一时间把这个弄好.呵呵.
 
LCD显示的信息图片如下:
 
 
LCD1602就是一个普通带字库的LCD.大家可以用它来显示数字和英文...同时显示一些简单的图形也是可以的.呵呵.这个得看个人的操作了...
 
1602可以显示2行、每行显示16个ASCII字符,并且可以自定义图形,只需要写入相对应字符的ASCII码就可以显示,使用上相对数码管更能显示丰富的信息,我们主要通过1602的显示程序来学习一下如何看时序图。  下面是1602各引脚的功能,具体不同厂家生产的引脚可能不一样,大家使用前要注意看厂家提供的资料。 
 
 
  D0~D7端为8位数据口,进行数据传送,而RS、R/W、E端则配合可以做出不同的操作,
对1602进行操作主要有四种,如下:  
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=高脉冲。输出:无  
 
从以上可以看出,如果想对1602进行何种操作,只要按其相对应的操作规程来做即可。  
 
虽然以上有四种操作,但实际上归类起来只有二种,一种读一种写。好了,我们接着看看,进行读与写时时序图: 
 
这张图初学者看起来可能有点晕,其实我们只要关注的地方是中间的Valid Data即有效数据区,我们进行读或写,无非都是想进行数据的传送,在时序图中,为了看起来更清楚些,我们画上两根红色,大家注意这个位置各个引脚的状态,先看读操作时序。 
 
 在进行读操作的时候,RW置于1,RS则根据读的内容(状态或数据)置为1或0,注意看图中的A和B两根红线,在A位置,E置为1,经过td时间后,可以在数据口读到正确的数据,由于td的时间极短(ns级),我们的单片机操作一般是us级,所以可以不考虑这个时间差,在将E置为1之后,就可以紧跟着指令去读取数据,在读到数据后,再将E置为0,经过THD2时间后,数据口上的数据失效。  
 
在进行写操作的时候,RW要置为0,RS根据写的内容不同(指令或数据)置为1或0,同时,大家注意C和D两根红线,我们在将E置为1之前,要先将数据送到数据口上,然后,在C位置,将E置为1,经过tPW延时后,再将E置为0,在这个时间段内必须保证数据口上的数据稳定不变,为有效的数据。同理,由于tPW这些延时相对较短(ns级),所以在单片里也不必考虑延时问题。 
 
因为LCD属于慢器件,在读写数据的时候需要的时间比较长,所以我们得写一个判断忙的函数.
读忙函数如下.
先将LCD引脚置高.
再读下引脚状态.如果引脚为高则等侍,如果时间到则退出读忙函数.
同时也要注意LCD,读忙可能会进入死循环.比如拔下LCD他就会有问题了.所以我们得加一个变量I.让这个函数在执行一段时间后退出....
 
有了读忙函数后,我们得写一个写入指令和数据的函数.
在这里面我们把写数据和指令二个合在一起,用一个变量来判断就可以让它处于写数据或指令的状态.这样非常方便实用..
先判断LCD忙不忙.如果不忙把输入的数据送到LCD端口.
再判断COMMAND状态,如果为1则写数据.为0则写指令.
再送一个高脉冲把数据写入LCD.
这样就完成了整个数据的写入...
 
有了写入数据还不能让LCD显示,我们还得需要写一个LCD的显示程序,把我们需要显示的东西指定显示在LCD哪个地方.比如在LCD 第1行,第十个位置显示.我们这个函数就得有一个X,Y坐标,还得有一个需要显示的数据.
 
请看下图...大家可以看得到,第二行的数据比第一行多了0X40.所以我们显示第二行,直接加上0X40就可以了.
 
 
X,Y是坐标...IN_DAT是需要显示的数据.
我们先把X和Y的值限制一下.让他们只能处于LCD显示的状态下.
我们再来判断当前是需要显示哪行...LCD有二行.如果Y=1则显示第二行.Y=0显示第一行.
把坐标计算出来了,就选写指令.
再写入显示数据.
这样就会在LCD上面可以看到你所写入的显示数据;
 
呵呵...你认为这样就完了吗?    那样就错了...LCD还是需要初始化的...如果没有初始化就能正常工作,也就像人一样没有告诉他他在做这工作前需要准备什么,那么他也是做不好这个工作的.
 
初始化程序.
初始化大家可以根据LCD的标准来写...下面也特别简单...在此我就不多讲了...
 
有了以上的函数.就可以正确的把数据显示在LCD上了..
 
现在我来教大家如何写一个在LCD上显示wang1jin-DIY的字符.
 
首先我们用KEIL建立一个工程文件....
这个会建立吧,呵呵,如果这个不会建立,你可以去bbs.cepark.com查查资料...也可以在里面请教一下版主或网友.
 
再建立一个MYTEPE.H
把下面的文件输入进去.
////////////////////////////////////////////////////////////////////////////////
//公司名称:电子园
//模块名:MYTEPE.H
//创建者:wang1jin
//修改者:
//功能描述:关键字重新定义;
//其它说明:
//创建日期:2009-07-10
//版本号:V1.0
//个人主页  :wang1jin.cepark.com
////////////////////////////////////////////////////////////////////////////////
#ifndef __MY_TYPE_H_
#define __MY_TYPE_H_
#define uint8 unsigned char
#define uint16 unsigned short int
#define uint32 unsigned long int
#define int8 signed char
#define int16 signed short int
#define int32 signed short long int
#define uint64 unsigned long long int
#define int64 unsigned long long int

#endif
-----------------------------------------------------------------------------------------------------------------------------------------
再建立一个LCD.H
把下面的文件也输入进去.
////////////////////////////////////////////////////////////////////////////////
//公司名称:电子园
//模块名:LCD.H
//创建者:wang1jin
//修改者:
//功能描述:LCD定义;
//其它说明:
//创建日期:2009-07-10
//版本号:V1.0
//个人主页  :wang1jin.cepark.com
////////////////////////////////////////////////////////////////////////////////
#ifndef __LCD_H__
#define __LCD_H__
#include"Mytype.h"
#include<AT89X52.H>
#define LCD_DATA P0
sbit RS="P1"^0;           //引脚定义;
sbit RW="P1"^1;
sbit EN="P1"^2;
void Read_Busy(void);          //读忙;
void Write_LCD(uint8 In_Data, bit Command);     //写数据或指令;
void Init_Lcd(void);          //LCD初始化;
void Write_Byte_Lcd(uint8 y,uint8 x,uint8 In_Data);    //显示数据;
void Delay_Ms(uint16 i);         //延时函数;
#endif
-----------------------------------------------------------------------------------------------------------------------------------------
再建立一个LCD.C
把下面的文件输入进去.
 
////////////////////////////////////////////////////////////////////////////////
//公司名称:电子园
//模块名:LCD.C
//创建者:wang1jin
//修改者:
//功能描述:LCD显示模块;
//其它说明:
//创建日期:2009-07-10
//版本号:V1.0
//个人主页  :wang1jin.cepark.com
////////////////////////////////////////////////////////////////////////////////
#include "Lcd.h"
void Init_Lcd(void)        //初始化LCD;
{
 Write_LCD(0x38,0);      //显示模式设置;
 Delay_Ms(10);       //延时;
 Write_LCD(0x38,0);
 Delay_Ms(10);
 Write_LCD(0x38,0);
 Delay_Ms(10);
 Write_LCD(0x38,0);
 Delay_Ms(10);
 Write_LCD(0x01,0);      //清除屏幕;
 Delay_Ms(10);
 Write_LCD(0x0C,0);      //开显示;
}
 

void Read_Busy(void)       //读忙函数;
{
 uint8 i = 255;        //定时延时时间;
 LCD_DATA = 0xFF;       //把LCD端口置1;
 RS = 0;         //把LCD设置在读状态;
 RW = 1;
 EN = 1;
 while((i--) && (LCD_DATA & 0x80 ));   //延时时间到或LCD不忙退出;
 EN = 0;         //关闭使能;
}
 
 
void Write_LCD(uint8 In_Data, bit Command)  //写数据和指令函数;
{
 Read_Busy();        //读忙;
 LCD_DATA = In_Data;      //送数据到LCD端口;
 RS = Command;       //RS为1写数据,为0写指令;
 RW = 0;
 EN = 1;         //产生一高脉冲写入数据;
 EN = 0;
}
 

void Write_Byte_Lcd(uint8 y,uint8 x,uint8 In_Data) //在指定位置写入一个字符;
{
 x &= 0x0F;        //X不大于15,不超出显示行;
 y &= 0x01;        //Y不大于1,不超出显示列;
 if(y)          //判断显示哪行;
  {
   x += 0x40;      //如果显示第二行则加0X40;
  }
 x += 0x80;        //如果没有加0X40则显示第一行;
 Write_LCD( x, 0 );       //写指令;
 Write_LCD( In_Data , 1 );     //写显示数据;
}

void Delay_Ms(uint16 i)       //延时MS级程序;
{
    uint8 j,k;
    for(;i>0;i--)
        {
            for(j=2;j<0;j--)
                {
                    for(k=244;k>0;k--);
                }
        }
}
-----------------------------------------------------------------------------------------------------------------------------------------
最后建立一个MAIN.C
把下面文件输入进去...
////////////////////////////////////////////////////////////////////////////////
//公司名称:电子园
//模块名:MAIN.C
//创建者:wang1jin
//修改者:
//功能描述:主程序;
//其它说明:
//创建日期:2009-07-10
//版本号:V1.0
//个人主页  :wang1jin.cepark.com
////////////////////////////////////////////////////////////////////////////////
#include<AT89x52.h>
#include "Mytype.h"
#include "Lcd.h"
void main(void)
{
 Init_Lcd();          //初始化LCD;
 Write_Byte_Lcd(0,0,'w');       //显示W;下面的以此类推;
 Write_Byte_Lcd(0,1,'a');
 Write_Byte_Lcd(0,2,'n');
 Write_Byte_Lcd(0,3,'g');
 Write_Byte_Lcd(0,4,'1');
 Write_Byte_Lcd(0,5,'j');
 Write_Byte_Lcd(0,6,'i');
 Write_Byte_Lcd(0,7,'n');
 Write_Byte_Lcd(0,8,'-');
 Write_Byte_Lcd(0,9,'D');
 Write_Byte_Lcd(0,10,'I');
 Write_Byte_Lcd(0,11,'Y');
 while(1);           //执行死循环;
}
操作完了以上的步骤后,我们来把它添加到KEIL中编译...
 
 
呵呵,一个LCD显示的模块就写完了....

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

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