最近CEPARK举办了DS1302时钟大赛,从实践中学会单片机活动.可能很多初学者网友并不会写出这样一个程序.在此我就把我的一些看法和DIY时钟的方法写出来和大家在一起共享一下.互相交流,互相学习,共同进步...
本文教考论坛的版主:SUNHM的教程...
在连载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
////////////////////////////////////////////////////////////////////////////////
#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
////////////////////////////////////////////////////////////////////////////////
#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
////////////////////////////////////////////////////////////////////////////////
#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.
////////////////////////////////////////////////////////////////////////////////
#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显示的模块就写完了....
建议大家手敲输入不要直接去复制...这样有利于你的学习.呵呵.
今晚上太晚了,明天给大家发上显示的效果...呵呵...
如果有什么问题请来我博客提问,大家互相交流...
我的个人小站:www.wang1jin.com
用户211764 2009-7-22 11:31
用户211764 2009-7-22 10:56
用户211764 2009-7-22 10:47
用户220339 2009-7-18 16:09
tengjingshu_112148725 2009-7-10 09:33
用户461316 2008-8-4 16:05
用户461316 2008-7-25 19:37