目录一、设计实验条件 (2)二、设计任务及要求 (2)1.设计任务 (2)2.要求 (2)三、设计报告内容 (2)1.前言 (2)2.总体方案设计 (3)1)系统总体结构 (3)2)芯片及其余部分选择 (3)3.硬件电路设计 (4)1)AT89S52单片机最小系统 (4)2)显示电路与AT89S52单片机接口电路设计 (5)4.软件设计 (5)1)主程序框图 (5)2)显示程序框图 (6)5.调试与测试结果 (6)1)实时显示 (6)2)修改显示内容 (7)3)闹钟功能 (8)6.心得体会 (8)四、附录 (9)1)程序 (9)2)系统电路图 (20)一、设计实验条件微机原理与接口实验室二、设计任务及要求1.设计任务采用AT89S52单片机及显示电路完成小时、分钟、秒的实时显示;2.要求(1)总体方案设计(2)硬件电路设计(3)软件设计(4)调试与测试结果(5)程序清单和系统原理图三、设计报告内容1.前言随着单片机技术的不断发展,单片机软硬件水平的不断提高,单片机已渗透到我们生活的各个领域,几乎很难找到哪个领域没有单片机的踪迹。
导弹的导航装置,飞机上各种仪表的控制,计算机的网络通讯与数据传输,工业自动化过程的实时控制和数据处理,广泛使用的各种智能IC卡,民用豪华轿车的安全保障系统,录像机、摄像机、全自动洗衣机的控制,以及程控玩具、电子宠物等等,这些都离不开单片机。
更不用说自动控制领域的机器人、智能仪表、医疗器械了。
因此,单片机的学习、开发与应用将产生非常重要的作用。
现在我们可以随意看到电子钟,电子钟是一种利用数字电路来显示秒、分、时的计时装置,与传统的机械钟相比,它具有走时准确、显示直观、无机械传动装置等优点,因而得到广泛应用。
随着人们生活环境的不断改善和美化,在许多场合需要数字电子钟,所以其极具有推广价值。
2.总体方案设计1)系统总体结构数字电子钟总体设计方框图如图1所示,主控制器采用单片机AT89S52,用四个按键开关选择显示内容以及修改显示内容,用6个7位共阳数码管以串口传送数据实图1 总体设计方框图2)芯片及其余部分选择2.1主控制器AT89S52是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
AT89S52具有以下标准功能:8k字节Flash,256字节RAM,32 位I/O 口线,看门狗定时器,2 个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。
另外,AT89S5可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。
空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
2.2 显示电路显示电路如图2所示,采用8255PA、PB口输出控制七段数码管显示。
图2 数码管显示2.3 控制按键共有四个控制按键,一个用于选择显示内容,一个用于修改当前值,一个用于加一,一个用于减一。
2.4 蜂鸣器在主控制器上接一个蜂鸣器,用于闹钟功能的实现。
3.硬件电路设计1)AT89S52单片机最小系统2)显示电路与AT89S52单片机接口电路设计4.软件设计1)主程序框图开始根据设置的初值开始显示,定时器开始工作,秒钟改变。
判断选择按键是否按下,若按下,根据按下次数显示内容判断修改按键是否按下,若按下,根据按下次数修改内容判断现在时分是否等于设定脑钟时分,若等于,则蜂鸣器响2)显示程序框图5.调试与测试结果1)实时显示开始数码管位选数码管段选返回继续执行以上三图为显示初始设置时分秒(00.01.11)、年月日(14.01.09)、以及闹钟时间(00.00.00)。
2)修改显示内容以上为修改显示内容结果。
3)闹钟功能6.心得体会四、附录1)程序/*******************************************************************///题目:数字电子钟设计//功能:采用AT89S52和显示电路实时显示时分秒、年月日的实时显示,并带闹钟功能//描述:通过置入初值来实现时间显示,通过按键控制显示内容和修改显示内容以及设置闹钟//连线:P3.0接开关1,P3.1接开关2,P3.2接开关3,P3.3接开关4,P3.4接蜂鸣器/*******************************************************************/#include<reg52.h>#include<absacc.h>#define Contadd XBYTE[0xFF23]#define PA XBYTE[0xFF20]#define PB XBYTE[0xFF21]#define adc XBYTE[0xFF80]#define uchar unsigned char#define uint unsigned intuchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管编码uint a=0,k1,k2,k3; //定义全局变量a、k1、k2uint sec,min,hou,day,mon,year; //定义秒,分,小时,日,月,年变量uint sec1=0,min1=0,hou1=0; //定义闹钟秒、分、小时变量,并赋值为0sbit XUANZE=P3^0; //定义选择显示内容选择按键P3.0 sbit XIUGAI=P3^1; //定义修改控制按键P3.1sbit UP=P3^2; //定义增加控制按键P3.2sbit DOWN=P3^3; //定义减小控制按键P3.3sbit beep=P3^4; //定义蜂鸣器控制按键P3.4/***********************延时程序*******************************************/ void delay(){ uchar i;i=50000000;while(i--);}/***********************数码管显示程序*************************************/ void display(uint m,uint n,uint p) //PA位选,PB段选{PA=0xfe;PB=table[m%10];delay();PA=0xfd;PB=table[m/10];delay();PA=0xfb;PB=table[n%10];delay();PA=0xf7;PB=table[n/10];delay();PA=0xef;PB=table[p%10];delay();PA=0xdf;PB=table[p/10];delay();}/************************修改程序0*******************************************/ void reset0(uint* x,uint max) //对x进行修改,x最大值max ,到达最大值变0 {if(UP==0){delay(); //消抖if(UP==0) //判断按键是否真正按下{ (*x)++;if((*x)>=max)(*x)=0;}while(UP==0) ;}if(DOWN==0){delay(); //消抖if(DOWN==0) //判断按键是否真正按下{ (*x)--;if((*x)<0)(*x)=max-1;}while(DOWN==0) ;}}/***********************修改程序1*****************************************/void reset1(uint* x,uint max) //对x进行修改,x最大值max,到达最大值变1{if(UP==0){delay(); //消抖if(UP==0) //判断按键是否真正按下{ (*x)++;if((*x)>=max)(*x)=1;}while(UP==0) ;}if(DOWN==0){delay(); //消抖if(DOWN==0) //判断按键是否真正按下{ (*x)--;if((*x)<1)(*x)=max-1;}while(DOWN==0) ;}}/***********************秒判断***************************************************/ void a_SEC()if(sec==60) //秒满60进1{sec=0;min++;}}/***********************分判断**********************************************/ void a_MIN(){if(min==60) //分满60进1{min=0;hou++;}}/***********************秒判断******************************************/void a_HOU(){if(hou==24) //小时满24进1{hou=0;day++;}}/***********************日判断**************************************/void a_DAY(){if(day==31) //日满31进1day=0;mon++;}}/***********************月判断***********************************************/void a_MON(){if(mon==13) //月满12进1{mon=0;year++;}}/***********************年判断***********************************************/void a_YEAR(){if(year==100) //年满100归0{year=0;}}/***********************选择显示内容***************************************/void key_xuanze(){if(XUANZE==0) //判断选择显示内容选择按键是否按下{k1=(k1+1)%3; //k1判断按下次数switch(k1) //通过判断k1来显示所要显示内容{case 0:display(sec,min,hou);break;case 1:display(day,mon,year);break;case 2:display(sec1,min1,hou1);break;}}}/************************修改内容******************************************/void key_xiugai(){if(XIUGAI==0) //判断修改控制按键是否按下{k3=1;k2=(k2+1)%7; //k2判断按下次数while(XIUGAI==0) //若修改控制按键未弹起,继续修改直至修改控制按键弹起{switch(k2){case 1:display(sec,min,hou);reset0(&min,60);break;case 2:display(sec,min,hou);reset0(&hou,24);break;case 3:display(day,mon,year);reset1(&day,31);break;case 4:display(day,mon,year);reset1(&mon,13);break;case 5:display(day,mon,year);reset1(&year,100);break;case 6:display(sec1,min1,hou1);reset0(&min1,60);break;case 0:display(sec1,min1,hou1);reset0(&hou1,60);k3=0;break;}}}}/***********************长延时程序*********************************************/ void delayl(){ uint i,j,q;for(i=0;i<100;i++){switch(k1) //长延时中判断k1调用显示程序,使得蜂鸣器响时数码管稳定显示{case 1:display(day,mon,year);break;case 0:display(sec,min,hou);break;case 2:display(sec1,min1,hou1);break;}for(j=0;j<2;j++)for(q=0;q<142;q++);}}/***********************蜂鸣器控制*************************************/void BEEP(){delayl();beep=~beep;}/***********************主程序*********************************************/void main(){Contadd=0x81; //设置8255A工作方式TMOD=0X01; //定时器0工作在方式1 ET0=1; //开定时器0中断EA=1; //开总中断TH0=(65536-50000)/256;TL0=(65536-50000)%256; //装入初值TR0=1; //开定时器0PA=0xdf;PB=0xff; //设定数码管初始显示k1=0;k2=0;k3=0; //设定k1、k2、k3初值sec=10;min=1;hou=0;day=9;mon=1;year=14; //设置秒、分、时、日、月、年初值display(sec,min,hou); //显示秒、分、时初值while(1) //死循环{if(XUANZE!=0&&XIUGAI!=0&&k3==0) //当显示内容选择按键位按下,也不进行修改内容操作时,判断k1选择显示内容{switch(k1){case 1:display(day,mon,year);break;case 0:display(sec,min,hou);break;case 2:display(sec1,min1,hou1);break;}}a_SEC();a_MIN();a_HOU();a_DAY();a_MON();a_YEAR(); //调用时分秒日月年判断程序if(XUANZE==0) //当选择控制按键按下时{ delay(); //消抖if(XUANZE==0) //判断按键是否真正按下{key_xuanze(); //调用显示内容选择程序}while(XUANZE==0) //当按键按下没有弹起时判断k1确定显示内容{switch(k1){case 1:display(day,mon,year);break;case 0:display(sec,min,hou);break;case 2:display(sec1,min1,hou1);break;}}}if(XIUGAI==0) //当修改控制按键按下{delay(); //消抖if(XIUGAI==0) //判断修改控制按键是否真正按下{TR0=0; //关闭定时器0,防止修改过程中当秒数到达60时,引起分、时等跳变key_xiugai(); //调用修改程序}TR0=1; //开定时器0}if((min1==min)&&(hou1==hou)) //当设置的闹钟时分和实时时分相等时闹钟开始工作{if(min1!=0||hou!=0) //闹钟初始值为0时0分,防止未设置闹钟引起闹钟工作{BEEP(); //调用蜂鸣器程序}}elsebeep=1; //当设置时分与实时时分不相等时关闭蜂鸣器}}void time() interrupt 1 //中断1程序{ TH0=(65536-50000)/256;TL0=(65536-50000)%256; //再次装入初值a++;if(a>=20) //当1s时,秒数加一{a=0;sec=sec+1;}}2)系统电路图。