基于单片机的实时时钟.docx
《基于单片机的实时时钟.docx》由会员分享,可在线阅读,更多相关《基于单片机的实时时钟.docx(26页珍藏版)》请在冰豆网上搜索。
基于单片机的实时时钟
目录
1.设计要求与方法论证...............................................3
1.1设计要求.....................................................3
1.2系统基本方案选择和论证.......................................3
1.2.1单片机芯片的选择方案和论证.................................3
1.2.2显示模块选择方案和论证.....................................4
1.3电路设计最终方案决定.........................................4
2.系统的硬件设计与实现.............................................4
2.1电路设计框图.................................................4
2.2系统硬件概述.................................................5
2.3系统硬件模块.................................................5
2.3.1AT89C51....................................................5
2.3.2DS1302.....................................................6
2.3.3点阵式LCD..................................................7
3.系统的软件设计...................................................7
4.硬件电路调试.....................................................7
5.结论.............................................................9
6.致谢.............................................................9
参考文献...........................................................10
附录...............................................................11
实时时钟
摘要:
二十一世纪是数字化技术高速发展的时代,而单片机在数字化高速发展的时代扮演着极为重要的角色。
实时时钟的开发与研究在信息化时代的今天亦是当务之急,因为它有极广阔的应用市场,可以说遍及人们生活的每一个角落。
本文设计的实时时钟属于小型智能家用电子产品。
利用单片机进行控制,实时时钟芯片DS1302时钟芯片进行记时,本文设计的实时时钟具有读数方便,操作简单,适用范围宽等特点。
关键字:
实时时钟,Proteus,51单片机,DS1302
1.设计要求与方案论证
1.1设计要求
(1)采用DS1302作为实时时钟芯片进行计时
(2)读出DS1302中的时间数据
(3)能显示时间数据,包括年月日,时分秒
(4)显示方式不限
1.2系统基本方案选择和论证
1.2.1单片机芯片的选择方案和论证
方案一:
用中小规模集成电路74/54系列和CC4000系列及555集成电路构建秒脉冲源,再利用分频器、计数器、缓存器等得到分、时、日、月、年的计时信号,最后用译码器驱动数码管显示,得到时钟功能。
方案二:
采用AT89C51单片机,完全兼容MCS-51系列单片机的所有功能,并且本身带有2K的内存储器,可以在编程器上实现闪烁式的电擦写达几万次以上,比以往惯用的8031CPU外加EPROM为核心的单片机系统在硬件上具有更加简单方便等优点,具体如下:
1)AT89C51单片机是最早期也最典型的产品,低功耗、高性能、采用CHMOS工艺的8位单片机。
2)它在硬件资源和功能、软件指令及编程上与Intel80C3X单片机完全相同。
在应用中可直接替换。
3)在AT89C51内部有FLASH程序存储器,既可用常规的编程器编程,也可用在线使之处于编程状态对其编程。
编程速度很快,擦除时也无需紫外线,非常方便。
4)AT89C5X系列可认为是Intel80C3X的内核与AtmelFLASH技术的结合体。
它为许多嵌入式控制系统提供了灵活、低成本的解决方案。
方案比较:
由两种方案可以看出,用方案一实现设计要求需要使用大量的集成电路,系统结构复杂,电路连接困难。
单个芯片的质量对系统的稳定性影响甚大,逻辑功能出现错误不易定位,整体调试费时费力。
扩展系统功能工作量极大,甚至有可能要将整个设计方案推倒重来。
方案二利用单片机作为控制核心,硬件按照技术手册要求连接后基本不需要调试,相关的逻辑功能全部由软件实现,修改方便。
功能扩展只需要在现有程序的基础上增加函数即可实现,无需对已实现功能的程序进行改动,调试方便,问题定位快捷、准确。
综上所述,我们采用方案二实现系统总体要求。
1.2.2显示模块选择方案和论证
方案一:
采用LED数码管动态扫描,LED数码价格适中,对于显示数字最合适,而且采用动态扫描方法与单片机连接时,占用的单片机口线少,驱动电路简单,且LED在亮度、功耗、可视角度和刷新速率等方面,都更具很大的优势。
但所需数码管太多焊接困难极易出错,所以不采用LED数码管作为显示。
方案二:
采用点阵式LCD显示,LCD1602是字符型液晶,显示字母和数字比较方便,控制简单,功耗低,体积小,显示内容丰富,超薄轻巧,可以用电池供电,便于携带,成本较低。
在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。
本设计需要显示较多的数字和字符,因此,采用点阵式LCD显示。
1.3电路设计最终方案决定
综上各方案所述,对此次作品的方案选定:
采用AT89C51作为主控制系统;点阵式LCD作为显示;DS1302提供时钟。
2.系统的硬件设计与实现
2.1电路设计框图
2.2系统硬件概述
本电路是由AT89C51单片机为控制核心,具有在线编程功能,低功耗,能在4.5V超低压工作;显示部分用LCD1602实现,能够同时显示16x02即32个字符;时钟电路由DS1302提供,它是一种高性能、低功耗、带RAM的实时时钟电路,可以对年、月、日、星期、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V.采用三线接口与单片机进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
可产生年、月、日、周日、时、分、秒,具有使用寿命长,精度高和低功耗等特点,同时具有掉电自动保存功能,本设计中为DS1302增加了备用电池,当主电源掉电时,备用电池自动为其供电。
2.3系统硬件模块
2.3.1AT89C51
各引脚的功能为:
VCC:
供电电压。
GND:
接地。
P0口:
P0口为一个8位双向I/O口。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
P1口:
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
P2口:
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P3口:
P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。
作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3口也可作为AT89C51的一些特殊功能口,P3.0RXD(串行输入口),P3.1TXD(串行输出口),P3.2/INT0(外部中断0),P3.3/INT1(外部中断1),P3.4T0(记时器0外部输入),P3.5T1(记时器1外部输入)。
2.3.2DS1302
各引脚的功能为:
1:
Vcc2:
5V电源。
当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc22、3:
X1、X2是外接晶振脚(32.768KHZ的晶振);
4:
地(GND);
5:
CE/RST:
复位脚;
6:
I/O:
数据输入输出口(双向);
7:
SCLK:
串行时钟,输入;
8:
Vcc1:
备用电池端。
2.3.3点阵式LCD
3.系统的软件设计
4.硬件电路调试
当连接完电路、编写完程序以后,需要进行对各个器件进行检测,特别注意DS1302芯片。
进行仿真时如果LCD不显示数据应该检测编写的程序是否正确。
DS1302存在时钟精度不高,易受环境影响,出现时钟混乱等缺点。
DS1302可以用于数据记录,特别是对某些具有特殊意义的数据点的记录,能实现数据与出现该数据的时间同时记录。
这种记录对长时间的连续测控系统结果的分析及对异常数据出现的原因的查找具有重要意义。
传统的数据记录方式是隔时采样或定时采样,没有具体的时间记录,因此,只能记录数据而无法准确记录其出现的时间;若采用单片机计时,一方面需要采用计数器,占用硬件资源,另一方面需要设置中断、查询等,同样耗费单片机的资源,而且,某些测控系统可能不允许。
但是,如果在系统中采用时钟芯片DS1302,则能很好地解决这个问题。
DS1302与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM数据;D5~D1指定输入或输出的特定寄存器;最低位LSB(D0)为逻辑0,指定写操作(输入),D0=1,指定读操作(输出)。
在DS1302的时钟日历或RAM进行数据传送时,DS1302必须首先发送命令字节。
若进行单字节传送,8位命令字节传送结束之后,在下2个SCLK周期的上升沿输入数据字节,或在下8个SCLK周期的下降沿输出数据字节。
5.结论
本次设计使我对课堂上的理论知识有了进一步的了解,并增强了对单片机这门课程的兴趣,如点阵式液晶显示器LCD1602、时钟日历芯片DS1302,同时也暴露了我在知识上掌握不足的缺点,其次在设计中我使用了Proteus绘图软件,也熟悉了Proteus的常用操作。
在整个设计过程中,我到图书馆查阅了大量的资料,在网上浏览了大量的与课程设计课题有关的信息,较好的完成了设计,达到了预期的目的。
对硬件电路的设计、布局要先有一个总体的好的构思,才显得电路板美观、大方、直观;其次,对电路各个模块要实现的功能、芯片的原理和设计方法要在反复设计操作中不断熟悉,并且考虑和软件的协调工作关系;再次,对电路中各个原件的属性参数要多次推敲修改以达到合理而正确的设定。
在此次设计中,知道了做凡事要有一颗平常的心,不要想着走捷径,一步一脚印。
也练就了我们的耐心,做什么事都在有耐心。
在此次课程设计中我收获了很多很多东西,这是最重要的,同时整个设计过程使我学习新知识综合运用所学知识解决实际问题的能力得到了提高,为以后的学习打下良好的知识基础和技能基础。
6.致谢
在此设计即将完成之际,我首先要特别感谢我的指导老师刘宏老师,在设计的自始至终,他给予我们耐心细致的的指导与不断的鼓励,循循善诱,我才能顺利地完成我的课程设计。
他那种对待学生和蔼亲切,对待工作一丝不苟的品质和精神值得我们每一个人学习。
其次我还要由衷地感谢这四年来专业老师对我的谆谆教诲和帮助,使我学会了电子专业的各门学科知识和电子电路的设计等。
使自己四年来所学的理论知识和实践做到了有机的结合,进一步深化巩固自己的理论知识,获益匪浅。
通过课程设计我不但学到了新知识,而且对大学所学的知识进行了复习和巩固,在不断的学习和进步中也一次次地感到自己能力的有限和学习知识的永无止境。
再次感谢所有理解、关心和帮助过我的人。
参考文献
[1]蒋辉平.周国雄.基于Proteus的单片机系统设计与仿真实例[M].第一版.北京.机械工业出版社.2009年7月.
[2]冯乔.基于单片机的实时时钟设计[J].2009年06期.中国知网机构数字图书馆.
附录:
#include
#include"ds1302.h"
#include
sbitsclk=P1^6;
sbitio=P1^7;
sbitrst=P1^5;
uchartime_data[7]={12,1,11,12,18,5,55};//年周月日时分秒
uchartime2[]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//写地址
uchartime1[]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};//读地址
uchardisp[19];
voidwrite_ds1302_byte(uchartemp)//写单个字节
{
uchari;
for(i=0;i<8;i++)
{
sclk=0;
io=temp&0x01;
temp>>=1;
sclk=1;
}
}
voidwrite_ds1302(ucharadd,uchardate)//写数据
{
rst=0;
_nop_();
sclk=0;
_nop_();
rst=1;
_nop_();
write_ds1302_byte(add);
write_ds1302_byte(date);
rst=0;
_nop_();
io=1;
sclk=1;
}
ucharread_ds1302(ucharadd)//读数据
{
uchari,num;
rst=0;
_nop_();
sclk=0;
_nop_();
rst=1;
_nop_();
write_ds1302_byte(add);
for(i=0;i<8;i++)
{
num>>=1;
sclk=0;
if(io)
num|=0x80;
sclk=1;
}
rst=0;
_nop_();
sclk=0;
_nop_();
sclk=1;
io=1;
returnnum;
}
voidset_rtc()//对时间
{
uchari,j;
for(i=0;i<7;i++)
{
j=time_data[i]/10;
time_data[i]=time_data[i]%10;
time_data[i]=time_data[i]+j*16;
}
write_ds1302(0x8e,0x00);//去除写保护
for(i=0;i<7;i++)
{
write_ds1302(time2[i],time_data[i]);
}
write_ds1302(0x8e,0x80);
}
voidset_rtc1(ucharcc,uchardd)//对时间
{
ucharj;
//for(i=0;i<7;i++)
//{
j=dd/10;
dd=dd%10;
dd=dd+j*16;
//}
write_ds1302(0x8e,0x00);//去除写保护
//for(i=0;i<7;i++)
//{
write_ds1302(cc,dd);
//}
write_ds1302(0x8e,0x80);
}
voidread_rtc()//读时间
{
uchari;
for(i=0;i<7;i++)
{
time_data[i]=read_ds1302(time1[i]);
}
}
voidtime_pros()//处理函数把BCD码变成十进制
{
ucharyear,week,month,day,hour,minute,second;
year=time_data[0];
week=time_data[1];
month=time_data[2];
day=time_data[3];
hour=time_data[4];
minute=time_data[5];
second=time_data[6];
time.year=year/16*10+year%16;
time.week=week/16*10+week%16;
time.month=month/16*10+month%16;
time.day=day/16*10+day%16;
time.hour=hour/16*10+hour%16;
time.minute=minute/16*10+minute%16;
time.second=second/16*10+second%16;
}
#ifndef__DS1302_H__
#define__DS1302_H__
#defineucharunsignedchar
#defineuintunsignedint
voidwrite_ds1302_byte(uchartemp);
voidwrite_ds1302(ucharadd,uchardate);
ucharread_ds1302(ucharadd);
voidset_rtc();
voidread_rtc();
voidtime_pros();
voidset_rtc1(ucharcc,uchardd);
structTime
{
ucharyear;
ucharmonth;
ucharday;
ucharweek;
ucharhour;
ucharminute;
ucharsecond;
};
externstructTimetime;
#endif
#include
#include"zifuku.h"
#include"ds1302.h"
#defineucharunsignedchar
#defineuintunsignedint
sbitCS1=P2^0;//LCD右屏幕
sbitCS2=P2^1;//LCD左屏幕
sbitRS=P2^2;//LCD数据、指令寄存器
sbitRW=P2^3;//LCD读、写操作
sbitE=P2^4;//LCD使能信号,下降沿有效
structTimetime;
/*
自定义延时子函数
*/
voiddelayms(ucharz)
{
intx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*
判断LCD忙信号状态
*/
voidbuys()
{
intdat;
RW=1;
RS=0;
do
{
P0=0x00;
E=1;
dat=P0;
E=0;
dat=0x80&dat;
}while(!
(dat==0x00));
}
/*
LCD写指令函数
*/
voidw_com(ucharcom)
{
//buys();
RW=0;
RS=0;
E=1;
P0=com;
E=0;
}
/*
LCD写数据函数
*/
voidw_date(uchardate)
{
//buys();
RW=0;
RS=1;
E=1;
P0=date;
E=0;
}
/*
LCD选屏函数
*/
voidselect_screen(ucharscreen)
{
switch(screen)
{
case0:
//选择全屏
CS1=0;
CS2=0;
break;
case1:
//选择左屏
CS1=0;
CS2=1;
break;
case2:
//选择右屏
CS1=1;
CS2=0;
break;
/*case3:
//选择右屏
CS1=1;
CS2=1;
break;
*/
}
}
/*
LCDx向上滚屏显示
*/
voidlcd_rol()
{
intx;
for(x=0;x<64;x++)
{
select_screen(0);
w_com(0xc0+x);
delayms(500);
}
}
/*
LCD清屏函数:
清屏从第一页的第一列开始,总共8页,64列
*/
voidclear_screen(screen)
{
intx,y;
select_screen(screen);//screen:
0-选择全屏,1-选择左半屏,2-选择右半屏
for(x=0xb8;x<0xc0;x++)//从0xb8-0xbf,共8页
{
w_com(x);
w_com(0x40);//列的初始地址是0x40
for(y=0;y<64;y++)
{
w_date(0x00);
}
}
}
/*
LCD显示汉字字库函数
*/
voidlcd_display_hanzi(ucharscreen,ucharpage,ucharcol,uintmun)
{//screen:
选择屏幕参数,page:
选择页参数0-3,col:
选择列参数0-3,mun:
显示第几个汉字的参数
inta;
mun=mun*32;
select_screen(screen);
w_com(0xb8+(page*2));
w_com(0x40+(col*16));
for(a=0;a<16;a++)
{
w_date(hanzi[mun++]);
}
w_com(0xb8+(page*2)+1);
w_com(0x40+(col*16));
for(a=0;a<16;a++)
{
w_date(hanzi[mun++]);
}
}
/*
LCD显示字符字库函数
*/
voidlcd_