单片机电子时钟系统设计论文
- 格式:doc
- 大小:733.50 KB
- 文档页数:16
一、设计内容利用单片机内部的定时/计数器,中断系统,按键以及八段数码管等元器件,设计一个具有校时功能,闹铃功能的数字钟。
该数字钟选用单片机AT89C51控制,6位LED数码管由软件编译直接驱动显示。
该时钟能显示当前的时、分、秒,可以进行计时,校准、定时闹铃。
电路结构简单,系统控制方便。
二、电路原理多时刻定时数字钟电路图如下。
单片机AT89C51外接12MH Z的晶振。
P0口输出字形码,P2口味扫描的字形码。
显示电路采用6只共阳极数码管,其共阳极由三极管8550驱动。
蜂鸣器作闹铃,也是由三极管8550驱动。
单片机各端口分配如下: P1.0:S1校时按钮P1.1: S2校分按钮P1.2: S3定时设置存储按钮P1.3: S4定时设置退出按钮P3.0:HA 蜂鸣信号电源:采用USB 接电脑USB 获得5V标准工作电压。
时间调整:分别按下校时、校分按钮S1、S2即可调整校时,持续不放,时、分数值连续加1,此操作使秒值清零。
定时设置:按下定时设置存储按钮S3,计时显示切换到定时时间值显示,初值为“00”时“00”分“00”秒。
再按S1设时数值,按S2设分数值,每按一下数值加1,调整到设定值时,再按S3保存第一闹铃时刻。
然后再分别按S1、S2校时校分,再按S3保存第二闹铃时刻,如此可设定24个闹铃时刻。
每次设好异时空都可以按S4退出定时设置状态,恢复正常走时、在操作过程中会听到“滴滴”声提示。
数码管显示原理:6只共阳数码管由6个三极管8550驱动,选通端接三极管的集电极,6个三极管的基极经电阻与分别与P2.0—P2.6相连,P2口做选通控制端,当输出0时相应的数码管被选通。
三、硬件电路制作与调试设计好电路原理图后就要完成硬件电路的制作与调试根据电路原理图,首先需要完成硬件电路的布局,一个好的布局不仅使整个硬件电路好看,而且能使焊接变得更简单,不易出现引脚间的短路,因此要合理布局。
然后就是焊接。
首先要完成主要元器件的焊接,第一步先将单片机的DIP40引脚插座焊到插件板上。
第二步就要焊接数码管,因为使用6个共阳的数码管,因此在焊接是需要将各个数码管的字型输入端并连起来,最后分别接入P0口,P0口需串如排阻,起上拉电阻作用。
由P0口输出字形控制码。
将各个数码管的公共选通端与对应三极管8550的c 端连接。
三极管8550的基极经电阻与P2.0—P2.6相连,e端都接+Vcc。
第三步是焊接时间调节电路。
时间调节电路由四个按键构成,与P1.0—P1.3相连,当按键动作时会有高或低电平(1或0)输入,单片机根据输入读取信息调节显示时间和设置闹铃时间。
第四步焊接复位电路和闹铃蜂鸣器电路。
复位电路由复位按键和电解电容组成。
闹铃蜂鸣器经三极管8550与P3.0口相连,当启动闹铃程序后,P3.0输出0,蜂鸣器开始蜂鸣。
最后一步焊接晶振电路。
采用12MHz晶振。
焊接完成后,仔细检查无明显短路引脚后,运行调试程序:MOV P0, #00HMOV P2, #00HSJMP $END若显示满屏“88.88.88”则说明硬件电路制作成功。
如不能正常显示则:1.观察触摸芯片等器件是否发烫,器件是否接反。
2.检查电源电压是否正常,整机电流应为200mA左右。
3.用示波器观察晶振引脚电压波形,判断震荡电路是否起振。
4.显示驱动电路是否正常。
、四、程序编写与调试1.编写思路:时钟信号将由单片机内部定时器T0中断产生,让T0工作在方式1循环产生50ms 时基信号,通过计数20次产生秒信号,在经过计数得分和时的信号。
因为采用定时器T0中断运行时不占CPU的时间,所以保证走时的精度。
程序开始内定时间为00点00分00秒,提供开机时使用,不然会出现显示乱码。
P1口的按钮信号采用查询法判别,当有效时,调用对应功能子程序。
多时刻闹铃程序采用数据对比法,先比较时数据,再比较分数据,与设定时刻相同时调用闹铃程序。
2.运行调试:软件编写调试采用“循序渐进法”,此方法尤其适合大型复杂程序的编写调试。
在本设计中我们先编写6位数码管动态扫描显示固定数值,如“012345”。
仿真烧写成功实现后,在此基础上添加定时中断并显示走时数值程序,编写校时程序。
最后嵌入定时存储设置和到时刻闹铃程序,如此完善整个程序的编写。
附:元器件列表1.单片机AT89C51 1个2.共阳极数码管 6个3.三极管8550 7个4.4.7KΩ电阻 8个5.10 KΩ电阻 5个6.排阻 1个7.30PF电容 2个8.10电容 1个9.10μF电解电容 1个10.蜂鸣器 1个11.12MHZ晶振 1个12.按键 5个13.LED灯 1个14.DIP 40 脚插座 1个15.电路板 1个16.开关 1个B外接口 1个18.连接用导线若干附:源程序代码;*********************************************************; 带有时间设置和秒显示的数字闹钟; Date : 2010.6.26 12MHZ晶振; Create by :赵红斌;P1.2设置键P1.0小时调整键P1.1分钟调整键P3.0定时输出指示;**************************************************************;*********************************************************; 变量地址分配;*********************************************************SwDelay equ 2; 设置按键时去抖动时间DisplayBuffer equ 30h; 设置显示缓冲区的地址为30h-35h共6个字节BeepVal equ 38h; 蜂鸣时间长短存储器地址OneSecondCounter equ 39h; 设置1秒计数器的地址,1秒计数器是用来计数1秒内计时器的中断次数Hour equ 3ah; 设置小时计数器的地址Minute equ 3bh; 设置分钟计数器的地址Second equ 3ch; 设置秒计数器的地址Year equ 3dh; 设置月日年计数器的地址Month equ 3eh;Day equ 3fh;P1Val equ 40h; 设置数码管位驱动值的地址ClockMode equ 20h.0; 模式(正常走时/闹时)设置寄存器地址,值为0时正常走时,为1时闹时设定AlarmOnOff equ 20h.1; 闹钟开启/关闭标志,为0关闭,为1开启AlarmTimeOn equ 20h.2; 此位为1时表示闹时时间到DataMode equ 20h.3DispHour equ 21h; 设置小时显示寄存器的地址DispMinute equ 22h; 设置分钟显示寄存器的地址DispSecond equ 23h; 设置秒显示寄存器的地址Dnum equ 24hAlarmHour equ 2eh; 设置闹时小时计数器的地址AlarmMinute equ 2fh; 设置闹时分钟计数器的地址AlarmSetKey bit P1.2; 闹钟设置键MinuteKey bit P1.1; 定义分设置键HourKey bit P1.0; 定义小时设置键DataSetKey bit p1.3;RelayOut equ P3.0; 定义输出引脚;**********************************************************************; 程序开始;********************************************************************** org 0000hajmp Reset ;程序开始org 000bh ;Timer0中断向量地址ajmp TimeInt ;跳到中断处理程序org 0020hReset: ;以下为初始化程序,为各个变量赋初值mov sp,#70h;setb RelayOutmov OneSecondCounter,#125;mov Hour,#00mov Minute,#00mov Second,#00 ;设置上电时时钟显示的初值;mov Year,#10mov Month,#6mov Day,#27;mov AlarmHour,#00mov AlarmMinute,#00 ;设置上电时闹时时间的初值;clr AlarmOnOff ;上点复位后闹时功能处于关闭状态clr ClockMode ;正常走时模式clr AlarmTimeOnsetb RelayOut ;清闹时输出clr DataMode;mov 36h,#10mov 37h,#11;;************************************; Use Timer 0 Mode 1; 400us interrupt;************************************mov tmod,#00000001bmov th0,#0E3hmov tl0,#5Dhmov ie, #82h ;开全局中断SETB EASETB ET0setb tr0 ;开定时中断;*****************************************; 主程序;*****************************************MainLoop:jb AlarmSetKey,CheckMinuteKey ;闹时设置键按下了吗?没有则转去检测秒设置键call Delayjb AlarmSetKey,CheckMinuteKey ;按下的时间超过500ms吗?setb ClockMode ;置为闹时设置模式call AlarmSetCheckMinuteKey:jb MinuteKey,CheckHourKey ;分设置键按下了吗?没有则转去检测小时设置键;如按下调用蜂鸣器发音程序mov a,Minuteadd a,#1; 如果按下则将分钟加一十进制调整mov Minute,a;cjne a,#3ch,NotOver1; 到60分钟了吗?mov Minute,#0; 到60分钟则将分钟清0NotOver1: ;以下等待按键释放及防抖动jnb MinuteKey,$CheckHourKey:jb HourKey,CheckDataKey;; 如按下调用蜂鸣器发音程序mov a,Houradd a,#1; 如果按下则将小时加1mov Hour,acjne a,#18h,NotOver2mov Hour,#0; 到24小时则将小时清0NotOver2: ;以下等待按键释放及防抖动jnb HourKey,$CheckDataKey:jb DataSetKey,CheckAlarmcall Delayjb DataSetKey,CheckAlarmsetb DataModecall DatasetCheckAlarm:jnb AlarmTimeOn,ToReturncall AlarmProcessToReturn:ajmp MainLoop;**********************************************; 定时器Timer0中断服务程序(此程序每8ms执行一次);**********************************************TimeInt:mov th0,#0E3h; 重新加载定时参数mov tl0,#5Dh;push accpush psw; 保护累加器及程序状态字的内容setb rs0; 选择工作寄存器组1,clr rs1; 这样可保护原工作寄存器组(0组)的内容djnz OneSecondCounter,NotoneSecond; 中断了125次了吗?即够1秒了吗?mov OneSecondCounter,#125; 如够1秒则重新设置"OneSecondCounter"计数器call Clock ; 调用将时钟内容加1秒的子程序call Daynumcall ConvertoBuffer ; 调用将时钟内容转换到显示缓冲区子程序NotoneSecond:call ScanDisplay ; 调用扫描显示子程序pop pswpop acc ; 恢复累加器及程序状态字的内容reti ; 中断返回;*********************************************; 扫描显示子程序;*********************************************ScanDisplay:MOV R1,#DisplayBuffer ;指向显示数据首址MOV R5,#01H ;扫描控制字初值PLAY:MOV A,R5 ;扫描字放入AMOV P2,A ;从P2口输出MOV A,@R1 ;取显示数据到AMOV DPTR,#TAB ;取段码表地址MOVC A,@A+DPTR ;查显示数据对应段码MOV P0,A ;段码放入P1口LCALL DelayINC R1 ;指向下一地址MOV A,R5 ;扫描控制字放入AJNB ACC.7,ENDOUT ;扫到第六位时结束RL A ;A中数据循环左移MOV R5,A ;放回R5内AJMP PLAY ;跳回PLAY循环ENDOUT: MOV P2,#0FFH ;一次显示结束,P2口复位MOV P0,#00H ;P1口复位RET ;子程序返回TAB: DB 40H ,79H ,24H, 30H,19H, 12H , 02H , 78H,00H, 10H , 08H , 03H,46H, 21H ,06H , 0EH;共阴段码表"0""1""2" "3""4""5""6""7" "8""9""-""c";****************************************************; 时钟内容加1秒的子程序;****************************************************Clock:mov a,Second; 将原秒值送入aadd a,#1; 加1秒mov Second,acjne a,#3cH,NotOverFlow; 够60秒了吗?mov Second,#0; 够了则将秒值清0;mov a,Minuteadd a,#1mov Minute,a; 分钟加1cjne a,#3cH,NotOverFlow; 够60分了吗?mov Minute,#0; 够了则将分值清0;mov a,Houradd a,#1mov Hour,a; 小时加1cjne a,#18H,NotOverFlow; 够24小时吗?mov Hour,#0; 够了则将小时值清0;mov a,Dayadd a,#1mov Day,acjne a,Dnum,NotAlarmmov Day,#1;mov a,Monthadd a,#1mov Month,acjne a,#13,NotAlarmmov Month,#1;mov a,Yearadd a,#1mov Year,acjne a,#11,NotAlarmmov Year,#0NotOverFlow:jnb AlarmOnOff,NotAlarm; 闹钟开启了吗?如没有开启则无需理会是否到闹时时间mov a,Secondjnz NotAlarm; 秒为零吗?mov a,Minutecjne a,AlarmMinute,NotAlarm; 时间分钟值和闹时设置分钟值相等吗?mov a,Hourcjne a,AlarmHour,NotAlarm; 时间小时值和闹时设置小时值相等吗?setb AlarmTimeOn; 到了闹时时间则将“闹时时间到”标志设为1NotAlarm:ret;**************************************************************************; 将时钟内容或闹时设置值转换到显示缓冲区子程序;************************************************************************** ConvertoBuffer:mov r1,#DisplayBufferjnb dataMode,TimeDispmov a,Daymov DispSecond,amov a,Monthmov DispMinute,amov a,Yearmov DispHour,aajmp ConvertTimeDisp: jb ClockMode,DispAlarmSet; 判断时钟模式,以决定是显示实时时间还是闹时时间mov a,Second;mov DispSecond,a;mov a,Minute;mov Dispminute,a;mov a,Hour;mov DispHour,a; 显示实时时间;ajmp ConvertDispAlarmSet:jb AlarmOnOff,AlarmOnmov DispSecond,#00hajmp NextAlarmOn:mov DispSecond,#11; 显示闹时时间及显示闹钟状态:显示“00”表示关闭闹钟,Next: ;“11”表示开启闹钟mov a,AlarmMinute;mov Dispminute,a;mov a,AlarmHour;mov DispHour,a;;Convert:mov a,DispSecond; 取秒值mov b,#10div abmov @r1,b;inc r1; 缓冲寄存器的地址加1mov @r1,a; 将秒值的十位值存入缓冲区;inc r1mov a,DispMinutemov b,#10div abmov @r1,b;inc r1; 缓冲寄存器的地址加1mov @r1,a; 将秒值的十位值存入缓冲区;inc r1mov a,DispHourmov b,#10div abmov @r1,b;inc r1; 缓冲寄存器的地址加1mov @r1,a; 将秒值的十位值存入缓冲区ret;;*******************************************************;天数判断,平年,闰年;******************************************************* Daynum: mov a,Monthmov dptr,#TABLmovc a,@a+dptrmov Dnum,amov a,Yearmov b,#4div abmov a,bcjne a,#0,BBmov a,Monthcjne a,#2,BBinc DnumBB: RETTABL: DB 31,32,29,32,31,32,31,32,32,31,32,31,32;**************************************************; 闹时设置子程序;**************************************************AlarmSet:jnb AlarmSetKey,$call Delay; 等待“AlarmSetKey”键释放CheckArmMinuteKey: ;jb MinuteKey,CheckArmHourKey; 分设置键按下了吗?没有则转去检测小时设置键setb AlarmOnOffmov 37h,#0mov a,AlarmMinuteadd a,#1; 如果按下则将分钟加1 十进制调整mov AlarmMinute,a;cjne a,#3ch,ArmNotOver1; 到60分钟了吗?mov AlarmMinute,#0; 到60分钟则将分钟清0ArmNotOver1: ;以下等待按键释放及防抖动jnb MinuteKey,$CheckArmHourKey:jb HourKey,AlarmSetEnd; 小时设置键按下了吗?没有则返回反复检测setb AlarmOnOffmov a,AlarmHouradd a,#1; 如果按下则将小时加1mov AlarmHour,acjne a,#18h,ArmNotOver2mov AlarmHour,#0; 到24小时则将小时清0ArmNotOver2: ;以下等待按键释放及防抖动jnb HourKey,$AlarmSetEnd:jb AlarmSetKey,AlarmSet; 设置完毕了吗?jnb AlarmSetKey,$;clr ClockMode; 从设置模式转为走时模式ret;*********************************************; 日期调整;*********************************************DataSet:jnb DataSetKey,$call DelayCheckDataYearKey:jb HourKey,CheckDataMonthKeymov a,Yearadd a,#1mov Year,acjne a,#11,DataNotOver1mov Year,#0DataNotOver1:jnb HourKey,$CheckDataMonthKey:jb MinuteKey,CheckDataDayKeymov a,Monthadd a,#1mov Month,acjne a,#13,DataNotOver2mov Month,#1DataNotOver2:jnb MinuteKey,$CheckDataDayKey:jb AlarmSetKey,DataSetEndmov a,dayadd a,#1mov Day ,acjne a,Dnum,DataNotOver3mov Day,#1DataNotOver3:jnb AlarmSetKey,$DataSetEnd:jb DataSetKey,DataSetjnb DataSetKey,$clr DataModeret;**************************************************; 闹时服务子程序;**************************************************AlarmProcess:clr RelayOut;jb AlarmSetKey,AlarmReturn; 停止闹时键(即闹时设置键)按下了吗?clr AlarmOnOffjnb AlarmSetKey,$;setb RelayOut; 如停止闹时键按下则停止闹时clr AlarmTimeOn;mov 37h,#11mov AlarmMinute,#00mov AlarmHour,#00AlarmReturn:ret;**************************************************; 延时子程序;************************************************** Delay:mov r6,#2Del:mov r7,#124djnz r7,$djnz r6,DelretDL1s: mov r3,#4dd: call Delaydjnz r3,ddretend。