基于51单片机的万年历设计说明.docx
- 文档编号:12520199
- 上传时间:2023-04-19
- 格式:DOCX
- 页数:50
- 大小:240.60KB
基于51单片机的万年历设计说明.docx
《基于51单片机的万年历设计说明.docx》由会员分享,可在线阅读,更多相关《基于51单片机的万年历设计说明.docx(50页珍藏版)》请在冰豆网上搜索。
基于51单片机的万年历设计说明
基于51单片机的电子万年历的设计
报告
第五小组
2012.2.22
1、项目概述
随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它所给人带来的方便也是不可否定的,要为现代人工作、科研、生活、提供更好的更方便的设施就需要从数单片机技术入手,一切向着数字化控制,智能化控制方向发展。
本设计是数据采集及处理,键盘控制,显示系统及报警系统与单片机有效结合,本设计是通过在“单片机原理及应用”课堂上学习的知识的综合应用,以及查阅资料,培养一种自学的能力。
并且引导一种创新的思维,把学到的知识应用到日常生活当中。
在设计的过程中,不断的学习,思考和同学间的相互讨论,运用科学的分析问题的方法解决遇到的困难,掌握单片机系统一般的开发流程,学会对常见问题的处理方法,积累设计系统的经验,充分发挥教学与实践的结合。
全能提高个人系统开发的综合能力,开拓了思维,为今后能在相应工作岗位上的工作打下了坚实的基础。
2、项目要求
1具有年、月、日、星期、时、分、秒等功能;
2具有温度计功能;
3具备年、月、日、星期、时、分、秒校准功能;
3、系统设计
1、框图设计
2、知识点
(1)时钟芯片DS1302的工作原理:
DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置“0”,接着把RST端置“1”,最后才给予SCLK脉冲;读/写时序如下图4所示。
图5为DS1302的控制字,此控制字的位7必须置1,若为0则不能把对DS1302进行读写数据。
对于位6,若对程序进行读/写时RAM=1,对时间进行读/写时,CK=0。
位1至位5指操作单元的地址。
位0是读/写操作位,进行读操作时,该位为1;该位为0则表示进行的是写操作。
控制字节总是从最低位开始输入/输出的。
表6为DS1302的日历、时间寄存器内容:
“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。
“WP”
是写保护位,在任何的对时钟和RAM的写操作之前,WP必须为0。
当“WP”为1时,写保护位防止对任一寄存器的写操作。
(2)DS1302的控制字节
DS1302的控制字如表-1所示。
控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出
RAMRD
1A4A3A2A1A0
/CK/WR
表-1DS1302的控制字格式
(3)数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
如下图-4所示
图-4DS1302读/写时序图
(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
1
电阻
10k(1/4w)
5
电阻
1k
5
电阻
200欧姆
5
电阻
4.7k
5
电阻
4.7k
5
电位器
10k
1
电容
10u/16V
1
电容
30p
4
三极管
9013
1
轻触按键
小(尺寸6×6mm×5.5)
4
蜂鸣器
5V
1
晶振
12M(小体积)
1
底座
8脚
1
底座
40脚
1
发光二极管
红
1
发光二极管
绿
1
时钟芯片
DS1302
1
纽扣电池及底座
3V(大)
1
液晶插槽
20孔
1
单排针
3排
120
杜邦线及杜邦头
1股
40
电路板
AOA5
1
5、软件设计
本系统的软件系统主要分为主程序、液晶程序、时钟程序。
1.程序流程图
主程序框图
设置流程图
2.程序清单
(1).主程序:
#include
#include
#include"ds1302.h"
#include"ds18b20.h"
#include"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(2,6,0*16,25);//[-]
Display(2,6,2*16,18);//调
Display(2,6,3*16,19);//整
Display(1,6,0*16,23);//小
Display(1,6,1*16,33);//时
Display(1,6,3*16,24);//[+]
break;
case3:
//日期
Display(2,6,0*16,25);//[-]
Display(2,6,2*16,18);//调
Display(2,6,3*16,19);//整
Display(1,6,0*16,7);//日
Display(1,6,1*16,11);//期
Display(1,6,3*16,24);//[+]
break;
case4:
//月份
Display(2,6,0*16,25);//[-]
Display(2,6,1*16,32);
Display(1,6,7*16,32);
Display(2,6,2*16,18);//调
Display(2,6,3*16,19);//整
Display(1,6,0*16,9);//月
Display(1,6,1*16,20);//份
Display(1,6,3*16,24);//[+]
break;
case5:
;//年份
Display(2,6,0*16,25);//[-]
Display(2,6,2*16,18);//调
Display(2,6,3*16,19);//整
Display(1,6,0*16,8);//年
Display(1,6,1*16,20);//份
Display(1,6,3*16,24);//[+]
break;
case6:
//星期
Display(2,6,0*16,25);//[-]
Display(2,6,2*16,18);//调
Display(2,6,3*16,19);//整
Display(1,6,0*16,10);//星
Display(1,6,1*16,11);//期
Display(1,6,3*16,24);//[+]
break;
default:
break;
}
}
/*-----------------------显示温度---------------------------*/
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;
}
if(i<0)
{
LED3=0;
LED1=LED2=1;
}
if(i>=40)
{
LED2=0;
LED1=LED3=1;
}
a=i/1000;//千位
b=i/100%10;//百位
c=i/10%10;//十位
if(i<0)
{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);//"℃"//(2[左半屏],1[第2行],1[第2列]*16[汉字],1[第1个汉字])
}
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);
else
DS1302_SetTime(&CurrentTime);
//写时间例如:
12-12-12
lcd_disptime(&CurrentTime);//显示时间
//写公历日期例如:
09-01-01
lcd_dispdate(&CurrentTime);//显示日期
tiaozheng();//调整状态显示
if(!
KEY3)
Lcd_t=0;
}
}
}
voidTimer_0(void)interrupt1
{
EA=0;
TH0=(65536-8000)/256;
TL0=(65536-8000)%256;
Lcd_t++;//显示定时计数器,当为10时进行显示,时间10ms
if(((!
KEY0)|(!
KEY1)|(!
KEY2)|(!
KEY3))&(key_flag==0))
{
timer=0;//清除不按键计数器
key_flag=10;//设计
while(--key_flag);//延时去抖动
key_flag=1;
if(!
KEY0)//Modle键,进入调时模式
{
if(key_operate==0)
{
key_flag=0;//允许按键长按
w=1;//调时标志位,为1时进入调时
if(counter++>50)//Modle键要长按1S生效
{
key_operate++;
key_flag=1;//不允许按键长安
}
}
else
{
key_operate++;
if(key_operate>6)
key_operate=1;
}
}
elseif(!
KEY1&&w==1)//减1调整
{
switch(key_operate)
{
case1:
//分钟
if(CurrentTime.Minute--==0)CurrentTime.Minute=59;
break;
case2:
//小时
if(CurrentTime.Hour--==0)CurrentTime.Hour=23;
break;
case3:
//日
if(CurrentTime.Day--==1)CurrentTime.Day=31;
break;
case4:
//月
if(CurrentTime.Month--==1)CurrentTime.Month=12;
break;
case5:
//年
if(CurrentTime.Year--==0)CurrentTime.Year=99;
break;
case6:
//
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 51 单片机 万年历 设计 说明