基于51单片机的万年历设计说明文档格式.docx
《基于51单片机的万年历设计说明文档格式.docx》由会员分享,可在线阅读,更多相关《基于51单片机的万年历设计说明文档格式.docx(50页珍藏版)》请在冰点文库上搜索。
(4)DS1302的寄存器
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表-2。
表-2DS1302的日历、时间寄存器
此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。
时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。
DS1302与RAM相关的寄存器分为两类:
一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;
另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
4、硬件设计
本电路是由AT89S51单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压工作;
时钟电路由DS1302提供,它是一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31*8的用于临时性存放数据的RAM寄存器。
可产生年、月、日、周日、时、分、秒,具有使用寿命长,精度高和低功耗等特点,同时具有掉电自动保存功能;
温度的采集由DS18B20构成;
1、电路原理图
2、元件清单
名称
型号
数量
单片机
AT89SC51
1
液晶显示器
JHD12864F
电阻
10k(1/4w)
5
电阻
1k
200欧姆
4.7k
电位器
10k
电容
10u/16V
30p
4
三极管
9013
轻触按键
小(尺寸6×
6mm×
5.5)
蜂鸣器
5V
晶振
12M(小体积)
底座
8脚
40脚
发光二极管
红
绿
时钟芯片
DS1302
纽扣电池及底座
3V(大)
液晶插槽
20孔
单排针
3排
120
杜邦线及杜邦头
1股
40
电路板
AOA5
5、软件设计
本系统的软件系统主要分为主程序、液晶程序、时钟程序。
1.程序流程图
主程序框图
设置流程图
2.程序清单
(1).主程序:
#include<
reg51.h>
absacc.h>
#include"
ds1302.h"
ds18b20.h"
lcd12864.h"
//按键定义
sbitKEY0=P2^3;
//设置
sbitKEY3=P2^4;
//退出
sbitKEY1=P2^5;
//减
sbitKEY2=P2^6;
//加
sbitLED1=P3^0;
sbitLED2=P3^1;
sbitLED3=P3^2;
unsignedcharw=0;
//调时标志位
//键盘函数所要用到的变量
unsignedcharkey_operate=0;
//设置模式
unsignedchartimer=0;
unsignedcharkey_flag;
unsignedintcounter=0;
unsignedcharLcd_t=0;
//LCD刷新间隔
unsignedcharss;
//全局变量
unsignedintv,getdata,getdataa;
staticunsignedcharmenu=0;
//定义静态小时更新用数据变量
staticunsignedcharkeys=0;
staticunsignedchartimecount=0;
//定义静态软件计数器变量
unsignedintflag=0;
//定义并初始化flag
unsignedcharDS=10;
//定义并初始化DS
unsignedcharDSS=1;
//定义并初始化DSS
unsignedcharflag1=0;
unsignedcharflag2=0;
unsignedcharflag3=0;
unsignedcharflag4=0;
voidlcd_dispwendu(void);
//函数声明
/******************************************************************************/
voidInitTimer0(void)//产生10ms时间间隔
{
TMOD=(TMOD&
0XF0)|0X01;
//定时器0工作在模式1,16Bit定时器模式
TH0=(65536-8000)/256;
TL0=(65536-8000)%256;
TR0=1;
ET0=1;
//开启定时器和中断
EA=1;
//开始总中断
}
voidINIT_Clock(void)//初始化万年历
InitLCD();
//初始12864
ClearScreen(0);
//清屏
SetStartLine(0);
//显示开始行
Initial_DS1302();
//初始化ds1302
Init_DS18B20();
//初始化ds18b20
InitTimer0();
//调转到10ms的定时器中断函数
/*****************************************************************************/
voidDelayMM(unsignedinta)
{//延时函数1MS/次
while(a--);
}
//Displayen(2,0,0*8,t1);
//Displayen(1,0,63*8,3);
//(1[右半屏],0[第1行],63[第63列]*8[数字],3[第3个数字])
//Display(2,1,1*16,1);
//(2[左半屏],1[第2行],1[第2列]*16[汉字],1[第1个汉字])
/*-----------------------显示时间---------------------------*/
voidlcd_disptime(SYSTEMTIME*Time)
unsignedchars1,s2,f1,f2,m1,m2;
//定义时间映射局部变量(专用寄存器)
if(Time->
Second!
=ss)
{//判断是否需要更新
ss=Time->
Second;
//更新数据
if(flag!
=0){DS--;
if(DS<
=0)DSS=2;
if(DSS==2){flag--;
}}
else{flag=0;
DS=10;
DSS=1;
}
flag4=flag/600%6;
//分位十位的数据
flag3=flag/60%10;
//分位个位的数据
flag2=flag/10%6;
//秒位十位的数据
flag1=flag%10;
//秒位个位的数据
lcd_dispwendu();
//显示温度
s1=Time->
Hour/10;
s2=Time->
Hour%10;
f1=Time->
Minute/10;
f2=Time->
Minute%10;
m1=Time->
Second/10;
m2=Time->
Second%10;
Displayen(2,2,0*8,s1);
Displayen(2,2,1*8,s2);
Displayen(2,2,2*8,11);
//"
:
"
Displayen(2,2,3*8,f1);
Displayen(2,2,4*8,f2);
Displayen(2,2,5*8,11);
Displayen(2,2,6*8,m1);
Displayen(2,2,7*8,m2);
/*-----------------------显示日期---------------------------*/
voidlcd_dispdate(SYSTEMTIME*Time)
unsignedcharn1,n2,n3,n4,n5,n6,n7,n8,n9;
//定义局部变量
n1=Time->
YearH/10;
n2=Time->
YearH%10;
n3=Time->
Year/10;
n4=Time->
Year%10;
n5=Time->
Month/10;
n6=Time->
Month%10;
n7=Time->
Day/10;
n8=Time->
Day%10;
n9=Time->
Week%10;
Displayen(2,0,0*8,2);
//2
Displayen(2,0,1*8,0);
//0
Displayen(2,0,2*8,n3);
Displayen(2,0,3*8,n4);
Display(2,0,10*16,8);
//年
Displayen(2,0,6*8,n5);
Displayen(2,0,7*8,n6);
Display(1,0,0*16,9);
//月
Displayen(1,0,2*8,n7);
Displayen(1,0,3*8,n8);
Display(1,0,2*16,7);
//日
Display(1,2,9*16,10);
//星
Display(1,2,10*16,11);
//期
Display(1,2,11*16,n9);
/*-----------------------调整状态显示---------------------------*/
voidtiaozheng()
{
switch(key_operate)
{
case1:
//分钟
Displayen(2,6,2*8,12);
-"
Displayen(2,6,3*8,12);
Display(2,6,0*16,25);
//[-]
Display(2,6,2*16,18);
//调
Display(2,6,3*16,19);
//整
Display(1,6,0*16,21);
//分
Display(1,6,1*16,22);
//钟
Displayen(1,6,4*8,12);
Displayen(1,6,5*8,12);
Display(1,6,3*16,24);
//[+]
break;
case2:
//小时
Display(1,6,0*16,23);
//小
Display(1,6,1*16,33);
//时
break;
case3:
//日期
Display(1,6,0*16,7);
//日
Display(1,6,1*16,11);
//期
case4:
//月份
Display(2,6,1*16,32);
Display(1,6,7*16,32);
Display(1,6,0*16,9);
//月
Display(1,6,1*16,20);
//份
case5:
;
//年份
Display(1,6,0*16,8);
//年
case6:
//星期
Display(1,6,0*16,10);
//星
default:
}
/*-----------------------显示温度---------------------------*/
voidlcd_dispwendu()
unsignedchari=0;
unsignedchara=0,b=0,c=0;
//unsignedchartd;
i=ReadTemperature();
//读温度并送显
//td=1;
if(i<
40&
&
i>
=0)
LED2=0;
LED1=LED3=1;
0)
LED3=0;
LED1=LED2=1;
if(i>
=40)
LED1=LED3=1;
a=i/1000;
//千位
b=i/100%10;
//百位
c=i/10%10;
//十位
{Displayen(1,4,58*8,17);
}//"
else
{Displayen(1,4,58*8,18);
+"
Displayen(1,4,59*8,12);
Displayen(1,4,60*8,b);
//温度十位
Displayen(1,4,61*8,c);
//温度个位
Display(2,4,0*16,12);
Display(2,4,1*16,13);
Display(2,4,2*16,14);
Display(2,4,3*16,15);
Display(1,4,7*16,0);
//"
℃"
SYSTEMTIMECurrentTime;
main()
INIT_Clock();
//初始化万年历
Display(2,6,1*16,26);
Display(2,6,2*16,27);
Display(2,6,3*16,28);
Display(1,6,4*16,29);
Display(1,6,5*16,30);
Display(1,6,6*16,31);
while
(1)
{
if(Lcd_t>
10)
//从DS1302中得到时间
if(key_operate==0)
DS1302_GetTime(&
CurrentTime);
DS1302_SetTime(&
//写时间例如:
12-12-12
lcd_disptime(&
//显示时间
//写公历日期例如:
09-01-01
lcd_dispdate(&
//显示日期
tiaozheng();
//调整状态显示
if(!
KEY3)
Lcd_t=0;
voidTimer_0(void)interrupt1
EA=0;
Lcd_t++;
//显示定时计数器,当为10时进行显示,时间10ms
if(((!
KEY0)|(!
KEY1)|(!
KEY2)|(!
KEY3))&
(key_flag==0))
timer=0;
//清除不按键计数器
key_flag=10;
//设计
while(--key_flag);
//延时去抖动
key_flag=1;
KEY0)//Modle键,进入调时模式
if(key_operate==0)
{
key_flag=0;
//允许按键长按
w=1;
//调时标志位,为1时进入调时
if(counter++>
50)//Modle键要长按1S生效
key_operate++;
key_flag=1;
//不允许按键长安
else
{
if(key_operate>
6)
key_operate=1;
elseif(!
KEY1&
w==1)//减1调整
switch(key_operate)
//分钟
if(CurrentTime.Minute--==0)CurrentTime.Minute=59;
//小时
if(CurrentTime.Hour--==0)CurrentTime.Hour=23;
case3:
if(CurrentTime.Day--==1)CurrentTime.Day=31;
break;
case4:
if(CurrentTime.Month--==1)CurrentTime.Month=12;
case5:
if(CurrentTime.Year--==0)CurrentTime.Year=99;
case6:
//