单片机课程设计报告设计课题:简易电子时钟的设计专业班级:07通信1班学生姓名:黎捐学号:0710618134指导教师:曾繁政设计时间:2010.11.5—2010.12.20一、设计任务与要求(1)设计任务: 利用单片机设计并制作简易的电子时钟,电路组成框图如图所示。
(2)(2)设计要求:1)制作完成简易的电子时钟,时间可调整。
2)有闹钟功能。
二、方案设计与论证简易电子时钟电路系统由主体电路和扩展功能电路两主题组成,总体功能原理是以STC89C52单片机为主要的控制核心,通过外接4个独立式键盘作为控制信号源,八个七段数码管作为显示器件,蜂鸣器作为定时器件,单片机实时的去执行相应的功能。
在数码管上显示出来,此时通过不同的按键来观看和调节各种数据。
CPU 控制原理图如图1所示。
图1. CPU 控制原理图三、硬件系统的设计3.1 STC89C52控制模块STC89C52是一个低功耗高性能单片机,40个引脚,32个外部双向输入/输出(I/O )端口,同时内含2个外中断口,2个16位可编程定时计数器,2个全双工串行通信口,STC89C51可以按照常规方法进行编程,也可以在线编程。
其将通用的微处理器和Flash 存储器结合在一起,特别是可反复擦写的Flash 存储器可有效地降低开发成本。
MCS-52单片机内部结构8052单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线,现在我们分别加以说明: 中央处理器:中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU 负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。
数据存储器(RAM):8052内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编时间显示显示主控器(51单片机)时间 调整声音报 时(选做)址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。
图2. 单片机8052的内部结构程序存储器(ROM):8052共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。
定时/计数器(ROM):8052有两个16位的可编程定时/计数器,以实现定时或计数产生中断用于控制程序转向。
并行输入输出(I/O)口:8052共有4组8位I/O口(P0、 P1、P2或P3),用于对外部数据的传输。
全双工串行口:8052内置一个全双工串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。
中断系统:8052具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。
时钟电路:8052内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但8052单片机需外置振荡电容。
图3. 单片机的引脚图3.2 复位电路8051的复位方式可以是自动复位,也可以是手动复位,见下图4。
此外,RESET/V pd还是一复用脚,V cc掉电其间,此脚可接上备用电源,以保证单片机内部RAM的数据不丢失。
这里采用的是手动复位电路。
图4. 上电自动和手动复位电路图3.3时钟电路时钟是单片机的心脏,单片机各功能部件的运行都是以时钟频率为基准,有条不紊的一拍一拍地工作。
因此,时钟频率直接影响单片机的速度,时钟电路的质量也直接影响单片机系统的稳定性。
常用的时钟电路有两种方式:一种是内部时钟方式,另一种为外部时钟方式。
本文用的是内部时钟方式。
电路设计如图5所示。
图5. 内部和外部时钟方式图3.4单片机的最小系统单片机的最小系统是由电源、复位、晶振、/EA=1组成,图6. 单片机最小系统的结构图3.5 键盘功能模块根据系统的基本的要求,基于时间的观看和设定等功能,采用由四个键构成的独立式键盘分别接在STC89C52单片机的P1.4-P1.7,非常的方便,同时相对于独立式键盘大大节省了空间,在软件的设计时带来了极大的方便,使程序简易明了,可读性强。
图7.按键电路图本次设计中,四个键分别定义为M 键、S1键、S2键和T 键,对应着菜单与确定,加1控制,减1控制,返回控制,各键功能单一,操作起来十分的清晰与方便。
当用手按下一个键时,如图7所示,往往按键在闭合位置和断开位置之间跳几下才稳定到闭合状态的情况;在释放一个键时,也回会出现类似的情况。
这就是抖动。
抖动的持续时间随键盘材料和操作员而异,不过通常总是不大于10ms 。
很容易想到,抖动问题不解决就会引起对闭合键的识别。
用软件方法可以很容易地解决抖动问题,这就是通过延 迟10ms 来等待抖动消失,这之后,在读入键盘码。
图8. 按键抖动信号波形3.6 LED 显示电路显示电路显示模块需要实时显示当前的时间,即时、分、秒,因此需要6个数码管,另需两个数码管来显示横。
采用动态显示方式显示时间,硬件连接如下图所示,时的十位和个位分别显示在第一个和第二个数码管,分的十位和个位分别显示在第四个和第五个数码管,秒的十位和个位分别显示在第七个和第八个数码管,其余数码管显示横线。
LED 显示器的显示控制方式按驱动方式可分成静态显示方式和动态显示方式两种。
对于多位LED 显示器,通常都是采用动态扫描的方法进行显示,其硬件连接方式如下图所示。
键按前沿后沿闭合S 2S 3S 4S 5P 14P 15P 16P 17图9. 数码管的硬件连接示意图3.7 定时提示模块电子钟的另外一个要求功能是在定时到达时候发出闹铃,本次设计利用蜂鸣器来实现。
具有电路结构非常简单,控制极其方便等优点。
3.8 系统电路图总原理图.PCB图见附录元件类型名称型号数量单片机STC89C52RC 1液晶显示器1602A 1晶振12.000 1蜂鸣器HYDZ 1按键 5电容30nf 222U 1电阻460欧 110k微调 1排阻1K*8 1三极管NPN8050 1四、数字钟的软件设计系统的软件设计也是工具系统功能的设计。
单片机软件的设计主要包括执行软件(完成各种实质性功能)的设计和监控软件的设计。
4.1 系统软件设计流程图主程序是先开始,然后启动定时器,定时器启动后在进行按键检测,检测完后,就可以显示时间。
开始启动定时器按键检测时间显示图10. 主程序流程图按键处理是先检测M按键是否按下,M按键如果按下,就显示菜单;如果没有按下,就检测S1按键是否按下,S1按键如果按下,相应数字就加1;如果没有按下,就检测S2按键是否按下,S2按键如果按下,相应数字就减1;如果没有按下,就检测T键是否按下,T键如果按下,就返回或撤消选项,如果没有按下,就把时间显示出来。
定时器中断时是先检测1秒是否到,1秒如果到,秒单元就加1;如果没到,就检测1分钟是否到,1分钟如果到,分单元就加1;如果没到,就检测1小时是否到,1小时如果到,时单元就加1,如果没到,就显示时间。
时间显示是先秒个位计算显示,然后是秒十位计算显示,再是分个位计算显示,再然后是分十位显示,再就是时个位计算显示,最后是时十位显示。
4.2主程序:#include"keyscan.h"#include"speaker.h"sfr p2=0xa0;bit baoshi;bit lingsheng=0;uchar count;void time_dispose(); void time_compare(); void time_baoshi(uchar a);void T_init(){TMOD=0x01;TH0=(65536-49994)/256; TL0=(65536-49994)%25 6;EA=1;ET0=1;TR0=1;}void main() {DelayMs(10);DelayMs(10);lcd_init();now_time_show();P2=0xaa;T_init();SPK=1;while(1){keyscan();if(lingsheng){alarm_clock();lingsheng=0;baoshi=0;}if(baoshi){baoshi=0;if(!lingsheng){timing_speaker(shi);}}}}void time0(void)interrupt 1{TH0=(65536-49996)/256;TL0=(65536-49996)%256;count++;if(count==19){time_dispose();}if(count==20){count=0;now_time_show();P2=~P2;time_compare();}}void time_dispose() {miao++;if(miao==60){miao=0;fen++;if(fen==60){fen=0;shi++;if(shi==24){shi=0;day++;if(day==7)day=0;ri++;if(yue==1||yue==3||yue= =5||yue==7||yue==8||yue ==10||yue==12){ if(ri==32){ ri=1; yue++;if(yue==13){yue=1;year++;if(year==3000)year=2010;}}}if(yue==2){if(((year%4==0)&&(year%100!=0))||(year%400==0)){if(ri==30){ri=1;yue++;}}else if(ri==29){ri=1;yue++;}}if(yue==4||yue==6||yue==9||yue==11){ if(ri==31){ri=1;yue++;}}}}}}void time_compare(){if(alarm_on_off){if(shi==timing_hou)if(fen==timing_min)if(miao==timing_sec){lingsheng=1;}}if(fen==0)if(miao==0)baoshi=1;}报时程序#include<reg52.h>sbit SPK=P1^0;sbit stop_m=P1^4;voidspeak_delay(unsigned int cnt){unsigned int a,b;for(a=cnt;a>0;a--)for(b=65;b>0;b--);}void speak_us(){unsigned int a;a=40; while(a--);}voidtiming_speaker(unsignedchar ab){unsigned int i,j;if(ab==0)ab=24;for(j=ab;j>0;j--){ for(i=0;i<300;i++){speak_delay(1);SPK=!SPK;}SPK=1;speak_delay(3);for(i=0;i<1000;i++){speak_delay(1);SPK=!SPK;}SPK=1;speak_delay(1500);}SPK=1;}void alarm_clock(){unsigned int i,j;for(j=20;j>0;j--) {for(i=0;i<400;i++) {speak_delay(1); SPK=!SPK;}SPK=0;speak_delay(30); for(i=0;i<200;i++) {speak_delay(1); SPK=!SPK;} SPK=1;speak_delay(20);for(i=0;i<500;i++){speak_delay(1);SPK=!SPK;}SPK=1;speak_delay(20);for(i=0;i<1000;i++){speak_us();SPK=!SPK;}SPK=1;if(!stop_m){speak_delay(10);if(!stop_m){j=1;while(!stop_m);}}speak_delay(500);}SPK=1;}液晶显示程序#include<reg52.h>#define uchar unsigned char#define uint unsigned int sbit rs=P2^0;sbit rw=P2^1;sbit e=P2^2;uchar shiw,gew;ucharshi=12,fen=30,miao=30; uchartiming_hou=12,timing_m in=30,timing_sec; ucharnian1=20,nian2=10,yue= 6,ri=10,day=4;uint year=2010;uchar codexing[7][3]={{'S','U','N'}, {'M','O','N'},{'T','U','E'},{ 'W','E','D'},{'T','H','U'},{' F','R','I'},{'S','A','T'}}; uchar a;bit alarm_on_off=0;bit bf=1;code uchartime_set_1[]={"A:settim e"};code uchar time_set_2[]={"B:alarmclock"};code uchartime_up[]={"alarmclock"};void writ_com(uchar date){bf=1;rs=0;rw=1;while(bf){P0=0xff;e=1;a=P0;e=0;bf=a&0x80;}rw=0;P0=date;e=1;e=0;}void writ_date(uchar date){bf=1;rs=0;rw=1;while(bf){P0=0xff;e=1;a=P0;e=0;bf=a&0x80;}rs=1;rw=0;P0=date;e=1;e=0;}void lcd_init(){writ_com(0x38);writ_com(0x0c);writ_com(0x06);writ_com(0x01);writ_com(0x80);}void writ_str(ucharadd,uchar dat2){shiw=dat2/10;gew=dat2%10;writ_com(add);writ_date(0x30+shiw); writ_date(0x30+gew); }void time_setting(){uchar time_i;writ_com(0x01);writ_com(0x0f);writ_com(0x80);for(time_i=0;time_i<9;ti me_i++)writ_date(time_set_1[tim e_i]);writ_com(0xc0);for(time_i=0;time_i<13;ti me_i++)writ_date(time_set_2[tim e_i]);}void now_time_show() {writ_com(0x01);nian1=(uchar)(year/100); nian2=(uchar)(year%100);writ_str(0x81,nian1);writ_str(0x83,nian2);writ_date('-');writ_str(0x86,yue);writ_date('-');writ_str(0x89,ri);writ_com(0x8c);writ_date(xing[day][0]);writ_date(xing[day][1]);writ_date(xing[day][2]);writ_str(0xc4,shi);writ_date(':');writ_str(0xc7,fen);writ_date(':');writ_str(0xca,miao);}void timing_set(){uchar i;writ_com(0x01);writ_com(0x83);for(i=0;i<11;i++)writ_date(time_up[i]);writ_com(0xc0);if(alarm_on_off){ writ_date('O');writ_date('N');}else{ writ_date('O');writ_date('F');writ_date('F');}writ_com(0xc5);writ_date('0'+timing_hou/10);writ_date('0'+timing_hou%10);writ_date(':');writ_date('0'+timing_min/10);writ_date('0'+timing_min%10);writ_date(':');writ_date('0'+timing_sec/10);writ_date('0'+timing_sec%10);按键程序#include"lcd.h"sbit m=P1^4;sbit s1=P1^5;sbit s2=P1^6;sbit t=P1^7;bit sys;//0bit one_fan,two_fan; uchar time_od;void DelayMs(uint tim) { uint x,y;for(x=tim;x>0;x--) for(y=110;y>0;y--);}void set_dingshi() { if(!m){DelayMs(10);if(!m){time_od++;while(!m);switch(time_od){case1:writ_com(0xc6);break;case2:writ_com(0xc9);break;case3:writ_com(0xcc);break;case4:writ_com(0xc0);time_od=0;break;default:break;} } }if(!s1){DelayMs(10);if(!s1){DelayMs(180);switch(time_od){case0:alarm_on_off=1;timing_set();writ_com(0xc0);break;case1:timing_hou++;if(timing_hou==24)timing_hou=0;timing_set();writ_com(0xc6);break;case2:timing_min++;if(timing_min==60)timing_min=0;timing_set();writ_com(0xc9);break;case :timing_sec++;if(timing_sec==60)timing_sec=0;timing_set();writ_com(0xcc);break;default:break;} } }if(!s2){ DelayMs(10);if(!s2){DelayMs(180);switch(time_od) {case 0:alarm_on_off=0; timing_set();writ_com(0x c0);break;case1:timing_hou--;if(tim ing_hou==255)timing_ho u=23;timing_set();writ_com(0x c6);break;case2:timing_min--;if(ti ming_min==255)timing_ min=59;timing_set();writ_com(0x c9);break;case3:timing_sec--;if(tim ing_sec==255)timing_se c=59;timing_set();writ_com(0x cc);break;default:break;} } }if(!t){ DelayMs(10);if(!t){while(!t);two_fan=1;time_setting();writ_com(0xc0); } } }void set_systime(){if(!m){DelayMs(10);if(!m) {time_od++;while(!m);switch(time_od){case1:writ_com(0xc8);break;case2:writ_com(0xc5);break;case3:writ_com(0x84);break;case4:writ_com(0x87);break;case5:writ_com(0x8a);break;case6:writ_com(0x8d);break;case7:time_od=0;writ_com(0xcb);break;default:break;} }}if(!s1){DelayMs(10);if(!s1){DelayMs(180);switch(time_od){case0:miao++;if(miao==60)miao=0;now_time_show();writ_com(0xcb);break;case1:fen++;if(fen==60)fen=0;now_time_show();writ_com(0xc8);break;case2:shi++;if(shi==24)shi=0;now_time_show();writ_com(0xc5);break;case3:year++;if(year==2099)year=2000;now_time_show();writ_com(0x84);break;case4:yue++;if(yue==13)yue=1;now_time_show();writ_com(0x87);break;case 5:ri++;if(yue==2){ if(((year%4==0)&&(year%100!=0))||(year%400==0)){ if(ri==30)ri=1;}Elseif(ri==29)ri=1; }if(yue==4||yue==6||yue==9||yue==11)if(ri==31)ri=1;if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)if(ri==32)ri=1;now_time_show();writ_com(0x8a);break;case6:day++;if(day==7)day=0;now_time_show();writ_com(0x8d);break;default:break;}}}if(!s2){DelayMs(10);if(!s2){DelayMs(180);switch(time_od){case0:miao--;if(miao==255)miao=59;now_time_show();writ_com(0xcb);break;case1:fen--;if(fen==255)fen=59;now_time_show();writ_com(0xc8);break;case2:shi--;if(shi==255)shi=23;now_time_show();writ_com(0xc5);break;case3:year--;if(year==1999)year=2100;now_time_show();writ_com(0x84); break;case4:yue--;if(yue==0)yu e=12;now_time_show(); writ_com(0x87);break; case 5:ri--;if(yue==2) { if(((year%4==0)&&(ye ar%100!=0))||(year%400 ==0)){ if(ri==0)ri=29;}else if(ri==0)ri=28;}if(yue==4||yue==6||yue= =9||yue==11)if(ri==0)ri=30;if(yue==1||yue==3||yue= =5||yue==7||yue==8||yue ==10||yue==12)if(ri==0)ri=31;now_time_show();writ_c om(0x8a);break;if(ri==0)ri=31;now_time _show();writ_com(0x8a); break;case6:day--;if(day==255) day=6;now_time_show(); writ_com(0x8d);break;}}}if(!t){DelayMs(10);if(!t){ while(!t);two_fan=1;time_setting();writ_com(0x80);}}}void one_keyscan(){if(!m) //{DelayMs(10);if(!m){two_fan=0while(!m);if(!sys){time_od=0;now_time_show();writ_com(0xcb);while(!two_fan){set_systime();}}else{ timing_set();writ_com(0xc0);time_od=0;while(!two_fan){set_dingshi(); }}} }if(!s1){ DelayMs(10);if(!s1){writ_com(0x80);while(!s1);sys=0;} }if(!s2){ DelayMs(10);if(!s2){ writ_com(0xc0);while(!s2);sys=1;} }if(!t){ DelayMs(10);if(!t){ while(!t);one_fan=1;sys=0;writ_com(0x0c);now_time_show();TR0=1;} }}void keyscan(){ if(!m) {DelayMs(10);if(!m){TR0=0;one_fan=0;time_setting();writ_com(0x80);while(!m);while(!one_fan){one_keyscan();}}}五、调试过程硬件调试:拿到电路板后,检查有没有虚焊等错误后,我装上元件焊好,但是下载好程序后喇叭没有声音,经检查发现NPN三极管管脚顺序放错了,改正后硬件就没有错误了。