资源描述
资料内容仅供您学习参考,如有不当或者侵权,请联系改正或者删除。
设计说明书
一、 项目概述:
随着科技的快速发展, 时间的流逝,至从观太阳、 摆钟到现在电子钟, 人类不断研究, 不断创新纪录。美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS1302。它能够对年、 月、 日、 周日、 时、 分、 秒进行计时, 还具有闰年补偿等多种功能, 而且DS1302的使用寿命长, 误差小。对于数字电子万年历采用直观的数字显示, 能够同时显示年、 月、 日、 周日、 时、 分、 秒和温度等信息, 还具有时间校准等功能。该电路采用AT89C52单片机作为核心, 功耗小, 能在3V的低压工作, 电压可选用3~5V电压供电。
综上所述此万年历具有读取方便、 显示直观、 功能多样、 电路简洁、 成本低廉等诸多优点, 符合电子仪器仪表的发展趋势, 具有广阔的市场前景。
本设计是基于51系列的单片机进行的电子万年历设计, 能够显示年月日时分秒及周信息, 具有可调整日期和时间功能。在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。在硬件与软件设计时, 没有良好的基础知识和实践经验会受到很大限制, 每项功能实现时需要那种硬件, 程序该如何编写, 算法如何实现等, 没有一定的基础就不可能很好的实现。
具体实现功能:
(1) 显示年月日时分秒及星期信息
(2) 具有可调整日期和时间功能
(3) 与即时时间同步
二、 项目要求
以AT89C51单片机为核心的时钟, 在LCD显示器上显示当前的时间:
1、 使用字符型LCD显示器显示当前时间 。
2、 显示格式为”时时: 分分: 秒秒”。”年年—月月—日日”。
3、 用3个功能键操作来设置当前时间。功能键K1~K3功能如下 。
n K1—进入设置时间位开关。
n K2—设置数加
n K3—设置数减
程序序执行后工作指示灯LED闪动, 表示程序开始执行。
三、 系统设计及简图
1、 系统硬件概述
本电路是由AT89C52单片机为控制核心, 具有在线编程功能, 低功耗, 能在3V超低压工作; 时钟电路由DS1302提供, 它是一种高性能、 低功耗、 带RAM的实时时钟电路, 它能够对年、 月、 日、 周日、 时、 分、 秒进行计时, 具有闰年补偿功能, 工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信, 并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31*8的用于临时性存放数据的RAM寄存器。可产生年、 月、 日、 周日、 时、 分、 秒, 具有使用寿命长, 精度高和低功耗等特点, 同时具有掉电自动保存功能; 显示部份由LCD液晶显示屏显示。电路设计框图如图1所示:
LCD液晶显示屏显示模块
AT89C52
主控制模 块
键盘模块
DS1302时钟模块
图1
2、 主要单元电路的设计:
2.1单片机主控制模块的设计:
AT89C52单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3, MCS-51单片机共有4个8位的I/O口( P0、 P1、 P2、 P3) , 每一条I/O线都能独立地作输出或输入。单片机的最小系统,18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端,在片内它是振荡器倒相放大器的输入,XTAL2接外部晶振和微调电容的另一端,在片内它是振荡器倒相放大器的输出。第9引脚为复位输入端,接上电容,电阻及开关后够上电复位电路。如图2
图2
2.2时钟电路模块的设计
在DS1302的引脚排列中, 其中Vcc1为后备电源, Vcc2为主电源。在主电源关闭的情况下, 也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时, Vcc2给DS1302供电。当Vcc2小于Vcc1时, DS1302由Vcc1供电。X1和X2是振荡源, 外接32.768KHz晶振。RST是复位/片选线, 经过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能: 首先, RST接通控制逻辑, 允许地址/命令序列送入移位寄存器; 其次, RST提供终止单字节或多字节数据的传送手段。当RST为高电平时, 所有的数据传送被初始化, 允许对DS1302进行操作。如果在传送过程中RSTS置为低电平, 则会终止此次数据传送, I/O引脚变为高阻态。上电运行时, 在Vcc大于等于2.5V之前, RST必须保持低电平。只有在SCLK 为低电平时, 才能将RST置为高电平, I/O为串行数据输入端( 双向) 。SCLK始终是输入端。如图3
图3
2.3显示模块的设计
用1602为LCD显示模块, 直接把对应的引脚和最小系统上的引脚相连, 连接后用初始化程序对其进行简单的功能测试。测试成功后即可为实验所用。如图4
图4
2.4时间调整电路设计
调整时间用2个调整按钮, 1个作为移位、 控制用, 另外1个作为加和减用, 分别定义为控制按钮、 加按钮。在调整时间过程中, 要调整的位与别的位应该有区别, 因此增加了闪烁功能, 即调整的位一直在闪烁, 直到调整下一位。闪烁原理就是, 让要调整的一位每隔一定时间熄灭一次, 比如说50 m s。利用定时器计时, 当达到50 ms溢出时, 就送给该位熄灭符, 在下一次溢出时。再送正常显示的值, 不断交替, 直到调整该位结束。此时送正常显示值给该位, 再进人下一位调整闪烁程序。
四、 硬件设计
1、 电路的原理图
如图5所示
图5
2、 原件清单:
单片机89c52芯片一片
DS1302芯片一片
1602模块一个
按钮3个
电容3个
晶振2个
电阻2个、 排阻一个导线若干等等其它辅助材料
五、 软件设计
1、 程序流程图
图6
时间程序控制图:
图7
2、 程序清单:
/*****************1602时钟****************************/
#include <reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SECOND 0x81
#define MINUTE 0x83
#define HOUR 0x85
sbit rs=P1^0;
sbit rw=P1^1;
sbit ep=P1^2;
sbit DS1302_SCLK = P1^3;
sbit DS1302_IO= P1^4;
sbit DS1302_RST = P1^5;
sbit M=P3^2;
sbit U=P3^3;
sbit D=P1^7;
//sbit D=P0^7;
sbit H3=P0^3;
unsigned char sel=0;
uchar code DIS1[]={"08ji dian er ban "};
uchar code DIS2[]={"kechengsheji"};
/////////////////////////延时////////////////////////////////
void delay(uint ms)
{
unsigned int a,b;
for(a=0;a<ms;a++)
for(b=0;b<124;b++);
}
////////////////////////////////////////////////////////////
/***************DS1302驱动************************/
void DS1302_Write(uchar D)
{
uchar i;
for(i=0;i<8;i++)
{
DS1302_IO=D&0x01;
DS1302_SCLK=1;
DS1302_SCLK=0;
D=D>>1;
}
}
uchar DS1302_Read()
{
uchar TempDat=0,i;
for(i=0;i<8;i++)
{
TempDat>>=1;
if(DS1302_IO) TempDat=TempDat|0x80;
DS1302_SCLK=1;
DS1302_SCLK=0;
}
return TempDat;
}
void WDS1302(uchar ucAddr, uchar ucDat)
{
DS1302_RST = 0;
DS1302_SCLK = 0;
DS1302_RST = 1;
DS1302_Write(ucAddr);
DS1302_Write(ucDat);
DS1302_SCLK = 1;
DS1302_RST = 0;
}
uchar RDS1302(uchar ucAddr)
{
uchar ucDat;
DS1302_RST = 0;
DS1302_SCLK = 0;
DS1302_RST = 1;
DS1302_Write(ucAddr);
ucDat=DS1302_Read();
DS1302_SCLK = 1;
DS1302_RST = 0;
return ucDat;
}
void init_1302()
{
WDS1302(0x8e,0x00);//开保护寄存器
WDS1302(0x80,0x50);//秒
WDS1302(0x82,0x59);//分
WDS1302(0x84,0x23);//时
WDS1302(0x8A,0x07);//星期
WDS1302(0x86,0x01);//日
WDS1302(0x88,0x10);//月
WDS1302(0x8C,0x11);//年
WDS1302(0x90,0xab);//卷电流充电
WDS1302(0x8e,0x80);//关保护寄存器
}
/************************1602驱动**************/
bit lcd_bz()
{
bit result;
rs = 0;
rw = 1;
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P2 & 0x80);
ep = 0;
return result;
}
////////////////////////////////////////////////////////
void lcd_wcmd(unsigned char cmd)
{
while(lcd_bz());
rs = 0;
rw = 0;
ep = 0;
_nop_();
_nop_();
P2 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep= 0;
}
/////////////////////////////////////////////////////////
void lcd_pos(unsigned char pos)
{
lcd_wcmd(pos | 0x80);
}
/////////////////////////////////////////////////////////
void lcd_wdat(unsigned char dat)
{
while(lcd_bz());
rs = 1;
rw = 0;
ep = 0;
P2 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//////////////////////////////////////////////////////////
void lcd_init()
{
lcd_wcmd(0x38);
delay(1);
lcd_wcmd(0x0c);
delay(1);
lcd_wcmd(0x06);
delay(1);
lcd_wcmd(0x01);
delay(1);
}
/*********************调时函数*************************/
void set_time()
{
signed char address,item;
signed char max,mini;
if(M==0)
{
sel++;
delay(300);
if(sel==7) sel=0;
if(sel==2) {address=0x82; max=59;mini=0; }
if(sel==1) {address=0x84; max=23;mini=0; }
if(sel==4) {address=0x8c; max=99;mini=9;}
if(sel==5) {address=0x88; max=12;mini=1; }
if(sel==6) {address=0x86; max=31;mini=1; }
if(sel==3) {address=0x8A; max=07;mini=1;}
M=1;
}
item=((RDS1302(address+1))/16)*10 + (RDS1302(address+1))%16;
if(U == 0)
{
delay(200);
U=1;
item++;
}
// P0=0xf7;
// if(D==0)
// { delay(200);
// item--;}
//
if(D == 0)
{
delay(200);
D=1;
item--;
}
if(item>max) item=mini;
if(item<mini) item=max;
WDS1302(0x8e,0x00);//允许写操作
WDS1302(address,(item/10)*16+item%10); //写入DS1302 //转成BCD码
WDS1302(0x8e,0x80);//写保护, 禁止写操作
}
/*********************显示子函数**************/
uchar lcdshow_u(uchar i,uchar y)
{
lcd_wcmd(0x80+0x00+i);
lcd_wdat(y);
}
uchar lcdshow_d(uchar i,uchar y)
{
lcd_wcmd(0x80+0x40+i);
lcd_wdat(y);
}
/*******************显示函数*******************/
void display(void)
{
uchar x,y;
x=RDS1302(HOUR);//时
y=x;
x=x>>4; lcdshow_u(6,0x30+x);
y=y&0x0f; lcdshow_u(7,0x30+y);
lcdshow_u(8,':');
x=RDS1302(MINUTE);//分
y=x;
x=x>>4; lcdshow_u(9,0x30+x);
y=y&0x0f; lcdshow_u(0x0a,0x30+y);
lcdshow_u(0x0b,':');
x=RDS1302(SECOND);//秒
y=x;
x=x>>4; lcdshow_u(0x0c,0x30+x);
y=y&0x0f; lcdshow_u(0x0d,0x30+y);
x=RDS1302(0x8b);
y=x;
//x=x>>4; lcdshow_u(0x0e,0x30+x);
y=y&0x0f; lcdshow_u(0x0f,0x30+y);
x=RDS1302(0x8d);
y=x;
x=x>>4; lcdshow_d(8,0x30+x);
y=y&0x0f; lcdshow_d(9,0x30+y);
lcdshow_d(0x0a,'-');
x=RDS1302(0x89);
y=x;
x=x>>4; lcdshow_d(0x0b,0x30+x);
y=y&0x0f; lcdshow_d(0x0c,0x30+y);
lcdshow_d(0x0d,'-');
x=RDS1302(0x87);
y=x;
x=x>>4; lcdshow_d(0x0e,0x30+x);
y=y&0x0f; lcdshow_d(0x0f,0x30+y);
for(x=45;x>0;x--)
{
set_time();
delay(10);
}
}
/**************************主函数******************/
void main()
{uchar i;
lcd_init();
delay(10);
lcd_pos(0x03);
i = 0;
while(DIS1[i] != '\0')
{ lcd_wdat(DIS1[i]);
i++;
}
lcd_pos(0x42);
i = 0;
while(DIS2[i] != '\0')
{
lcd_wdat(DIS2[i]);
i++;
}
init_1302();
delay(1000);
for(i=0;i<17;i++)
{
lcdshow_u(i,'>');
delay(90) ;
}
for(i=0;i<17;i++)
{
lcdshow_d(i,'>');
delay(90) ;
}
lcd_init();
delay(10);
lcdshow_u(0,'T');
lcdshow_u(1,'i');
lcdshow_u(2,'m');
lcdshow_u(3,'e');
lcdshow_u(14,' ');
lcdshow_d(0,'D');
lcdshow_d(1,'a');
lcdshow_d(2,'t');
lcdshow_d(3,'e');
lcdshow_d(6,'2');
lcdshow_d(7,'0'); //LCD框架描绘
while(1)
{
set_time();
if(sel==2) {lcdshow_u(9,' ');lcdshow_u(0x0a,' ');delay(500); }
if(sel==1) {lcdshow_u(6,' ');lcdshow_u(7,' ');delay(500); }
if(sel==3) {lcdshow_u(14,' ');lcdshow_u(15,' ');delay(500); }
if(sel==5) {lcdshow_d(0x0b,' ');lcdshow_d(0x0c,' ');delay(500); }
if(sel==6) {lcdshow_d(0x0e,' ');lcdshow_d(0x0f,' ');delay(500); }
if(sel==4) {lcdshow_d(0x08,' ');lcdshow_d(0x09,' ');delay(500); }
//调时LCD闪烁显示
display();
}
}
六、 系统仿真及调试
仿真调试结果如图8所示:
图8
完成预期课程设计目的!
展开阅读全文