基于AT89c52单片机电子万年历设计带程序.docx
《基于AT89c52单片机电子万年历设计带程序.docx》由会员分享,可在线阅读,更多相关《基于AT89c52单片机电子万年历设计带程序.docx(19页珍藏版)》请在冰豆网上搜索。
基于AT89c52单片机电子万年历设计带程序
一、摘要·································2
二、设计································3
三、设计任务.···························2
四、设计要求·····························3五、系统方案设计·························3
1、系统································3
1)原理构成框图····················3
2)设计思路·························4
2、主程序设计························4
3、中断程序设计·······················5
5、时间调整电路的设计···············7
六、系统评价·····························7
七、c语言程序注释及说明··················8
一、摘要
单片机就是微控制器,是面向应用对象设计、突出控制功能的芯片。
单片机接上晶振、复位电路和相应的接口电路,装载软件后就可以构成单片机应用系统。
将它嵌入到形形色色的应用系统中,就构成了众多产品、设备的智能化核心。
本设计是基于AVR单片机强大的控制功能制作而成的电子万年历,该电子万年历包括四大功能:
实时显示年、月、日、时、分、秒、星期;人为的校正年、月、日、时、分、星期;第一次开机显示12-00-30。
二、设计目的
1、掌握C52程序用于实践并实现相应的功能;
2、掌握时钟程序的使用方法;
3、掌握时间函数的使用方法;
4、掌握键盘的程序使用方法;
三、设计任务
通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期等功能,并能准确计算闰年闰月的显示,七个按钮连接P0口可以精确调整每一个时间数值,通过对所设计的万年历时钟电路进行实验测试,达到了动态显示时间,随时调整时间等技术指标。
四、设计要求
(1)能够准确的计时,时间可在数码管上显示出来,默认显示为时、分、秒,每隔一分钟自动显示年、月、日及星期,也可通过按键控制显示,并可通过按键调节时间。
(2)第一次开机显示12-30-30。
(3)每半秒led彩灯闪烁一次
五、系统方案设计:
1、系统总体设计:
1)原理构成框图
本设计用AT89C52作为核心控制部分,外接晶振电路与复位电路,以两个四位数码管作为显示部分,开关控制显示时间与日期,具体框图如图1所示,数码管框图如图2所示:
图1原理框图
图2:
数码管模块
2)设计思路
通过一段时间对专业书籍及多种设计方案的研究分析,我采用了比较常用的AT89C52作为核心控制芯片,用C语言进行编程来满足设计的要求。
用LED数码管来实现年、月、日、时、分、秒、星期的显示,通过按键开关可以在日期与时间间切换和对时钟进行调整。
2、主程序的设计
系统程序采用C语言按模块化方式进行设计,然后通过KeilC51L软件开发平台将程序转变成十六进制程序语言,得到HEX文件,经过USB转串口线下载到单片机板上即可实现。
系统程序主要包括主程序、延时程序、显示处理程序、中断程序。
主程序流程图如图3所示:
图3主程序框图
3、中断程序设计
本设计中还有两个中断程序定时器0中断和定时器1中断,定时器1用来动态扫描,定时0零用来计时并且控制led灯的闪烁及年月日时分秒的自加一。
动态扫描框图这里不再画出。
定时器0中断框图如下:
N
Y
N
Y
N
Y
N
Y
N
Y
N
Y
图4中断程序框图
4、时间调整电路的设计
采用按键设计,该单片机有四个独立按键,分别为P3^0、P3^1、P3^2、P3^3独立式按键直接与单片机I/O口相连构成键盘,每个按键不会相互影响,这四个按键可控制时于分的加和减,调节年月日及星期时需要按键组合控制(具体方法见程序注释),键盘模块框图如下:
图5:
键盘模块
六、系统评价
该设计利用单片机内部的定时/计数器进行中断定时,配合软件延时实现时、分、秒的计时,该方案节省硬件成本,且能使设计者对单片机的指令系统能有更深入的了解,从而掌握单片机应用技术MCS-52c语言程序设计方法,因此,本系统设计采用此种软件控制方法来实现时,而由于ATMEL公司的AT89C52单片机是低功耗的具有4KB在线可编程FLASH存储器的单片机。
它与通用80C52系列单片机的指令第和引脚兼容。
片内的FLASH集成在一个芯片上,形成了功能强大、使用灵活和具有较高性能价格比的微控制器。
它的功能强大,而且也较容易购买。
总结:
所要实现的功能通过单片机编程就可以达到,不需要额外的时钟芯片来增加成本,并使外围电路更加简单明了。
七、c语言程序及注释说明:
/*
1、按键可以调整当时时间
2、按键可以调节定时时间
3、定时时间到继电器吸合
*8位数码管显示时间格式格式12-30-30表示:
12点30分30秒
S1用于小时加1操作
S2用于小时减1操作
S3用于分钟加1操作
S4用于分钟减1操作
*/
#include//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
sbitKEY1=P3^0;//定义端口参数
sbitKEY2=P3^1;
sbitKEY3=P3^2;
sbitKEY4=P3^3;
sbitKEY5=P3^6;
sbitKEY6=P3^7;
sbitKEY7=P3^5;
sbitLED=P1^2;//定义指示灯参数
codeunsignedchartab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f};
//共阴数码管0-9
unsignedcharStrTab[8];
//定义缓冲区
Unsignedcharminute=30,hour=12,second=45,month=12,day=26,
yea=2012r,week=1;
/*****************************************************/
/*延时函数*/
/******************************************************/
voiddelay(unsignedintcnt)
{
while(--cnt);
}
/******************************************************/
/*显示处理函数*/
/***************************************************/
voidDisplaypro(void)
{
if(((second>=0)&&(second<=1))||(KEY5==0))//显示年、月、日(自动或同时按下按键0和2)
{StrTab[0]=tab[year/1000];//年
StrTab[1]=tab[year/100%10];
StrTab[2]=tab[year/10%10];
StrTab[3]=tab[year%10];
StrTab[4]=tab[month/10];//月
StrTab[5]=tab[month%10];
StrTab[6]=tab[day/10];//日
StrTab[7]=tab[day%10];}
if((second==2)||(KEY6==0))//显示星期(自动或同时按下按键0和3)
{
StrTab[0]=0x40;
StrTab[1]=0x40;
StrTab[2]=0x40;//显示"-"
StrTab[3]=0x40;
StrTab[4]=0x40;//显示"-"
StrTab[5]=0x40;//显示"-"
StrTab[6]=0x40;//显示"-"
StrTab[7]=0x40;//显示"-"
StrTab[7]=tab[week];
}
if((second>=3)&&(second<=60)&&(KEY6==1)&&(KEY5==1))
{StrTab[0]=tab[hour/10];//显示小时
StrTab[1]=tab[hour%10];
StrTab[2]=0x40;//显示"-"
StrTab[3]=tab[minute/10];//显示分钟
StrTab[4]=tab[minute%10];
StrTab[5]=0x40;//显示"-"
StrTab[6]=tab[second/10];//显示秒
StrTab[7]=tab[second%10];}
}
/******************************************************/
/*主函数*/
/******************************************************/
main()
{
TMOD|=0x01;//定时器010msin12Mcrystal用于计时
TH0=0xd8;//初值
TL0=0xf0;
ET0=1;
TR0=1;
TMOD|=0x10;//定时器1用于动态扫描
TH1=0xF8;//初值
TL1=0xf0;
ET1=1;
TR1=1;
EA=1;
Displaypro();//调用显示处理
while
(1)//主循环
{
if((!
KEY1)&&KEY6&&KEY5)//按键1去抖以及动作
{
delay(10000);
if((!
KEY1)&&KEY6&&KEY5)
{
hour++;if(hour==24)hour=0;//正常时间小时加1
Displaypro();
}
}
if((!
KEY2)&&KEY6&&KEY5)//按键2去抖以及动作
{
delay(10000);
if((!
KEY2)&&KEY6&&KEY5)
{
hour--;if(hour==255)hour=23;//正常时间小时减1
Displaypro();
}
}
if((!
KEY3)&&KEY6&&KEY5)//按键3去抖以及动作
{
delay(10000);
if((!
KEY3)&&KEY6&&KEY5)
{
minute++;if(minute==60)minute=0;//分加1
Displaypro();
}
}
if((!
KEY4)&&KEY6&&KEY5)//按键4去抖以及动作
{
delay(10000);
if(!
KEY4)
{
minute--;if(minute==255)minute=59;//分减1
Displaypro();
}
}
if((!
KEY3)&&(!
KEY6))//按键去抖以及动作
{
delay(10000);
if((!
KEY3)&&(!
KEY6))
{
week++;if(week==8)week=1;//按键显示星期时如果按下8按键星期加1
Displaypro();
}
}
if((!
KEY4)&&(!
KEY6))//按键2去抖以及动作
{
delay(10000);
if((!
KEY4)&&(!
KEY6))
{
week--;if(week==0)week=7;//按键显示星期时如果按下c按键星期减1
Displaypro();
}
}
if((!
KEY2)&&(!
KEY5))//如果按键显示年、月、日时
{
delay(10000);
if((!
KEY2)&&(!
KEY5))
{
day++;
if((day>=29)&&(month==2)&&(year%4!
=0))
day=1;
if((day>=30)&&(month==2)&&(year%4==0))
day=1;
if((day>=31)&&(month==4||month==6||month==9||month==11))
day=1;
if((day>=32)&&(month==1||month==3||month==5||month==7||month==8||month==10||month==12))
day=1;
Displaypro();
}
}
if((!
KEY3)&&(!
KEY5))
{
delay(10000);
if((!
KEY3)&&(!
KEY5))
{
month++;if(month==13)month=1;
Displaypro();
}
}
if((!
KEY4)&&(!
KEY5))
{
delay(10000);
if((!
KEY4)&&(!
KEY5))
{
year0++;if(year0==100){year0=00;year1++;}
Displaypro();
}
}
if((!
KEY7)&&(!
KEY5))
{
delay(10000);
if((!
KEY7)&&(!
KEY5))
{
year0--;if(year0==255){year0=99;year1--;};
Displaypro();
}
}
}
}
/******************************************************/
/*定时器1中断*/
/******************************************************/
voidtime1_isr(void)interrupt3using0//定时器1用来动态扫描
{
staticunsignedcharnum;
TH1=0xF8;//重入初值
TL1=0xf0;
switch(num){
case0:
P2=0;P0=StrTab[num];break;//分别调用缓冲区的值进行扫描
case1:
P2=1;P0=StrTab[num];break;
case2:
P2=2;P0=StrTab[num];break;
case3:
P2=3;P0=StrTab[num];break;
case4:
P2=4;P0=StrTab[num];break;
case5:
P2=5;P0=StrTab[num];break;
case6:
P2=6;P0=StrTab[num];break;
case7:
P2=7;P0=StrTab[num];break;
default:
break;
}
num++;//扫描8次,使用8个数码管
if(num==8)
num=0;
}
/******************************************************/
/*定时器0中断*/
/******************************************************/
voidtim(void)interrupt1using1
{
staticunsignedcharcount;//定义内部静态变量
TH0=0xd8;//重新赋值
TL0=0xf0;
count++;
switch(count)
{
case0:
case20:
case40:
case60:
case80:
Displaypro();//隔一定时间调用显示处理
break;
case50:
P1=~P1;//半秒LED闪烁
break;
default:
break;
}
if(count==100)
{year=year1*100+year0;
count=0;
second++;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24)
{hour=0;
day++;
week++;
if(week==8)
week==1;
if((day>=29)&&(month==2)&&(year%4!
=0))
{day=1;
month++;
}
if((day>=30)&&(month==2)&&(year%4==0))
{day=1;
month++;
}
if((day>=31)&&(month==4||month==6||month==9||month==11))
{day=1;
month++;
}
If((day>=32)&&(month==1||month==3
||month==5||month==7||month==8||month==10||month==12))
{day=1;
month++;
}
if(month>=13)
year0++;if(year0==100){year0=00;year1++;}
}
}
}
}
}
THANKS!
!
!
致力为企业和个人提供合同协议,策划案计划书,学习课件等等
打造全网一站式需求
欢迎您的下载,资料仅供参考