一、系统概述:
1.基本要求:
(1) 显示准确的北京时间(时、分、秒),可用24小时制式;
(2) 随时可以调校时间。
(3) 增加公历日期显示功能(年、月、日),年号只显示最后两位;
(4) 随时可以调校年、月、日;
(5) 允许通过转换功能键转换显示时间或日期。
(6) 所有按键需要通过串口自发自收来调校各种功能。
2.发挥部分
(1)增加秒表功能
(2)增加闹铃功能
(3)增加整点报时功能。
实验功能:
本系统是基于单片机AT89S52制作的数字电子钟。根据实验要求,在完成实验所要求的基本功能外,扩展了几个功能。
硬件系统设计方面:
采用六位LED数码管,用切换的方式显示日期或时间和设置的闹钟时间;
可调整日期或时间以及闹钟时间;
具有设置闹钟的功能;
软件系统设计方面:
程序采用汇编语言编写,使自己更加理解硬件语言以及其工作原理。
“时钟”基准时间由单片机内部的定时中断提供用一个计数器对定时中断的次数进行计数,可实现“秒”定时,同理可以进行“分”﹑“时”定时,以及“日”﹑“月”﹑“年”定时,并充分考虑闰年等情况下的日期的差异
采用按键查询功能复用,简化了程序的设计
采用动态扫描法显示6位数码管
方案考虑:
1、硬件方案
(1)、采用6位LED数码管显示日期或者时间。
(2)、显示器的驱动可采用“静态显示驱动”(如7段译码/锁存/驱动芯片CD4511);也可采用“动态扫描驱动”,但后者比前者所需驱动电流要大。
(3)显示部分也可采用液晶,但液晶成本较高。
(4)、键盘的按键数目较多时则采用行列式矩阵结构为好。“一键多用”的构思和设计能大为减少按键的数目。
(5)、整体设计上应考虑其结构简单﹑操作简便﹑布局美观﹑成本低廉。
2、软件方案
(1)、“时钟”基准时间由单片机内部的定时中断提供,定时时间应是“秒”的整除数,且长短适宜。最长不能超过16位定时器的最长定时时间;最短不
能少于中断服务程序的执行时间。通常来说基准时间越短,越有利于提高时钟的运行精确度。
(2)、用一个计数器对定时中断的次数进行计数,可实现“秒”定时,同理可以进行“分”﹑“时”定时,以及“日”﹑“月”﹑“年”定时。
(3)、LED 数码管显示器采用“动态扫描驱动”时要注意的是:驱动信号的维持时间必须大于“起辉时间”(电流大起辉时间短),而驱动信号的间歇时间必须小于“余辉时间”(电流大余辉时间长),但驱动电流大小受硬件电路能力和LED数码管极限功耗的制约。
(4)、动态扫描显示方式在更新显示内容时,因LED数码管余辉的存在可能会造成显示字符的模糊,新内容写入显示器之前须将所有的LED数码管熄灭。
(5)、关于自动识别“月大﹑月小”和“平年﹑润年”问题的考虑
方案比较:
显示部分:
我们采用了数码管显示,鉴于数码管也能实现基本的功能,而且液晶成本又太昂贵,同时我们放弃了用译码芯片,一方面进一步降低成本,另一方面少了部分电路,减少错误产生。
焊接部分:
印制电路板的特点是布线紧凑、优点是美观,跳线少,线路稳定,主要的工作量在于前期原理图的绘制跟PCB板的布线,缺点是腐蚀容易不均匀而断线;而手工焊万用板优点是可变性高,自由度高,主要工作量是原理图的布线与跳线的构思跟焊接,缺点是电路板焊接麻烦。
我们选择手工焊万用板的原因:
1 原材料提供的只是万用板,从按照题目要求的方面考虑
2 万用板便于功能的扩展,板上也留了很多空位为创新功能使用。
按键部分
按键方面,主要是采用矩阵键盘扫描跟按键查询。矩阵键盘扫描法用到比较多的按键,使操作复杂,资源得不到充分利用。为了避免不必要的失误,所以采用“按键查询,一个功能一个按键”的方式,排列整齐,简洁美观
单片机作品实物图:
二、元器件清单:
IC
89S52
1
IC座
40脚
3
晶体振荡器
12MHz
1
微型按钮
4脚
5
LED发光二极管
红色
1
电阻
4.7K
2
电阻
1k
6
电阻
3K
6
电阻
330
7
排阻 1k 1
电解电容
10UF
1
万能电路板
块
1
LED七段数码管
共阳BS
6
晶体三极管
PNP8550
6
蜂鸣器 1
三.按键使用
(1)。P0.7口按键具有切换显示模式的功能
(2)。P0.6口按键具有闪烁位移位的功能
(3)。P0.5 口按键具有对闪烁位加一的功能
(4)。P0.4口按键具有计秒的功能,即开始秒表/停止秒表/清楚秒表,同时还具有停止闹钟的功能。
(5)第9口具有复位的功能。即一按下去后恢复到初始化状态
(6)串口自收自发功能,当p3.0与p3.1连接起来后,按键有效,但当p3.0与p3.1断开后,按键无效。
系统使用调试说明:
按开关key1次数 | 系统状态 |
0 | (50)=00H,(51H)=00H,正常显示时间 |
1 | (50)=01H,(51H)=00H,正常显示日期 |
2 | (50)=02H,(51H)=00H,正常显示闹铃 |
3 | (50)=03H,(51H)=00H,正常显示秒表 |
4 | (50)=00H,(51H)=00H,正常显示时间 |
按键2:
按开关key2次数 | 系统状态 |
0 | (50)=00H,(51H)=00H,不闪烁 |
1 | (50)=00H,(51H)=01H,低两位闪烁 |
2 | (50)=00H,(51H)=02H,中两位闪烁 |
3 | (50)=00H,(51H)=03H,高两位闪烁 |
4 | (50)=00H,(51H)=00H,不闪烁 |
数码管显示代码表:
数码管管脚号 | Dp | g | f | e | d | c | b | a | 数码管显示值 | 编码数值 |
P1端口 | P1.7 | P1.6 | P1.5 | P1.4 | P1.3 | P1.2 | P1.1 | P1.0 |
端口电平 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | C0H |
1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0F9H |
1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 2 | 0A4H |
1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 3 | 0B0H |
1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 99H |
1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 5 | 92H |
1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 6 | 82H |
1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 7 | 0F8H |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8 | 80H |
1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 9 | 90H |
主程序流程图:
当有不同按键,进入不同的服务子程序,同时在查询的时候判断是不是整点,有没有到达闹铃设置的时间
进入服务子程序采用的是查询的模式。
显示模式调整流程图:
显示标志位位50h
闪烁位移位:其中设定闪烁标志位为51H.当它变化时标志着不同的闪烁位
闪烁位加一子程序:对当前闪烁的位进行加一
file:///D:/Personal/Temp/ksohtml/wps_clip_image-8871.png其中
同理对于分,时,日,月,年,都要判断是否到达最大数,是则分,时,清0,日,月,年置一,
秒表子程序
闹铃功能子程序:
整点报时子程序流程图:
TO中断子程序:
日历子程序
- 附程序清单:
- ;;;;;;;;;;;;;;;;;;;
- ;预定义部分;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;
- ;预定义用来显示小时、分钟、秒钟的存储单元
- secL equ 30h;秒的十位
- secH equ 31h;秒的个位
- minL equ 32h;
- minH equ 33h;
- hourL equ 34h;
- hourH equ 35h;
- dayL equ 36h
- dayH equ 37h
- monL equ 38h
- monH equ 39h
- yearL equ 3ah
- yearH equ 3bh
- als_l equ 40h;
- als_h equ 41h;
- alm_l equ 42h;
- alm_h equ 43h;
- alh_l equ 44h;
- alh_h equ 45h;
- xsbz equ 50h;
- shanshou equ 51h;
- mao_sfw equ 5ah;秒的十分位
- mao_bfw equ 5bh;秒的百分位
- mao_sw equ 5ch;秒的十位
- mao_gw equ 5dh; 秒的各位
- mao_qw equ 5eh;qianwei
- mao_bw equ 5fh;baiwei
- org 0000h;复位入口
- ljmp main
- org 000bh;定时器T0入口
- ljmp time0
- org 0003h;外部中断0入口
- reti;
- org 0013h;外部中断1入口
- reti
- org 001bh;定时器T1入口
- ljmp time1;
- org 0023h;串行中断入口
- reti
- ;;;;;;;;;;;;;;;;;;;;;;
- ;主程序入口;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;
- main:
- ;放置初始值,H表示低地址,L表示高地址
- mov secH,#0h
- mov secL,#5h
- mov minH,#9h
- mov minL,#5h
- mov hourH,#2h
- mov hourL,#1h
- mov yearH,#8h
- mov yearL,#0h
- mov monH,#1h
- mov monL,#1h
- mov dayH,#0h
- mov dayL,#2h
- mov als_l,#3h;
- mov als_h,#1h;
- mov alm_l,#3h;
- mov alm_h,#0h;
- mov alh_l,#1h;
- mov alh_h,#2h;
- mov mao_sfw ,#00h;秒的十分位
- mov mao_bfw ,#00h;秒的百分位
- mov mao_sw,#00h ;秒的十位
- mov mao_gw,#00h ; 秒的各位
- mov mao_qw,#00h;
- mov mao_bw,#00h;
- mov 50h,#00h;
- mov 51h,#00h;
- clr p3.2;
- MOV SCON,#90H;串行口工作于方式2
- ;定时器T0,T1设置
- mov TMOD,#11H;设置T0与T1为16位定时器
- mov TL0,#0b0h;
- mov TH0,#3ch;T0初值为3cb0h定时50ms
- mov TL1,#0f0h;
- mov TH1,#0d8h;T1初值为fc18h定时10ms
- setb pt0;
- setb EA;总中断允许
- setb et0;
- setb TR0;开启T0中断开始记时
- mov r4,#20;定时次数,刚好1s
- mov 60h,#0ah;定时器1定时次数10次
- start:
- lcall display;
- jnb P0.7,k0;
- jnb p0.6,k1;
- jnb p0.5,k3;
- jnb p0.4,k4;
- lcall naoling1;
- lcall zhengdi
- jmp start;
- k0: lcall chxianshi;
- k1: lcall k2
- k4: ljmp jimiao;
- ;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;闪烁位加一
- ;;;;;;;;;;;;;;;;;;;;;;;;;
- k3: lcall dl30ms;
- jb p0.5,outout;
- set12: jnb p0.5,set12;
- lcall chuan;
- mov a,50h;
- cjne a,#01h,sjiantz;
- mov a,51h;
- cjne a,#01h,zhwei;
- mov r1,#dayH;
- lcall add1;
- mov a,r3;
- cjne a,#32h,ftiao;分若小于则转退出
- mov dayH,#01h;否则清0
- mov dayL,#00h;
- ftiao: ljmp outout;
- zhwei: cjne a,#02h,gwei;
- mov r1,#monH;
- lcall add1;
- mov a,r3;
- cjne a,#13h,outout;
- mov monH,#01h;
- mov monL,#00h;
- ljmp outout;
- gwei: cjne a,#03h,outout;
- mov r1,#yearH;
- lcall add1;
- mov a,r3;
- cjne a,#99h,outout;
- mov yearH,#00h;
- mov yearL,#00h;
- ljmp outout;
- outout: ljmp start; 跳出
- sjiantz:cjne a,#00h,naozhtz;转闹钟调整
- mov a,51h;
- cjne a,#01h,zhwei2;
- mov r1,#secH;
- lcall add1;
- mov a,r3;
- cjne a,#60h,ftiao2;分若小于则转退出
- mov secH,#00h;否则清0
- mov secL,#00h;
- ftiao2: ljmp outout;
- zhwei2: cjne a,#02h,gwei2;
- mov r1,#minH;
- lcall add1;
- mov a,r3;
- cjne a,#60h,outout;
- mov minH,#00h;
- mov minL,#00h;
- ljmp outout;
- gwei2: cjne a,#03h,outout;
- mov r1,#hourH;
- lcall add1;
- mov a,r3;
- cjne a,#24h,outout;
- mov hourH,#00h;
- mov hourL,#00h;
- ljmp outout;
- naozhtz:mov a,51h;
- cjne a,#01h,zhwei3;
- mov r1,#als_h;
- lcall add1;
- mov a,r3;
- cjne a,#60h,ftiao3;分若小于则转退出
- mov als_h,#00h;否则清0
- mov als_l,#00h;
- ftiao3: ljmp outout;
- zhwei3: cjne a,#02h,gwei3;
- mov r1,#alm_h;
- lcall add1;
- mov a,r3;
- cjne a,#60h,outout;
- mov alm_h,#00h;
- mov alm_l,#00h;
- ljmp outout;
- gwei3: cjne a,#03h,outout;
- mov r1,#alh_h;
- lcall add1;
- mov a,r3;
- cjne a,#24h,outout;
- mov alh_h,#00h;
- mov alh_l,#00h;
- ljmp outout;
- ;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;naoling
- ;;;;;;;;;;;;;;;;;;;;;;;;;
- naoling1:push acc;
- setb p0.1
- mov a,31h;
- cjne a,41h,out6;
- mov a,30h;
- cjne a,40h,out6;
- mov a,33h;
- cjne a,43h,out6;
- mov a,32h;
- cjne a,42h,out6;
- mov a,35h;
- cjne a,45h,out6;
- mov a,34h;
- cjne a,44h,out6;
- nao: clr P0.1
- lcall display
- jnb P0.4,stopnao
- sjmp nao
- stopnao: lcall dl30ms
- mov P0,#0ffH
- out6: pop acc;
- lcall display;
- ret;
- ;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;整点报时;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;
- zhengdi: push acc;
- mov a,31h;
- cjne a,#00h,out7;
- mov a,30h;
- cjne a,#00h,out7;
- mov a,33h;
- cjne a,#00h,out7;
- mov a,32h;
- cjne a,#00h,out7;
- mov a,#0ah;
- clr p0.1;
- clr p0.3
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- lcall display;
- setb p0.1;
- setb p0.3
- out7: pop acc;
- lcall display;
- ret;
- ;**************************************************
- ;函数名:
- ;功能: 串口发送数据函数
- ;传入参数: 无
- ;传出参数: A
- ;**************************************************
- chuan: MOV A,p0 ;读取P1口数据
- MOV SBUF,A
- JNB TI,$ ;等待发送完毕
- CLR TI
- lcall dl30ms;
- wait: jnb ri,out9;
- MOV A,SBUF
- CLR RI
- sjmp out10;
- out9: lcall display;
- jmp chuan;
- out10: ret;
-
- ;**************************************************
- ;函数名:chxianshi
- ;功能: 显示调整函数
- ;传入参数: 无
- ;传出参数:
- ;**************************************************
- chxianshi: lcall dl30ms;
- jb P0.7,set2;
- set1: jnb p0.7,set1;
- lcall chuan;
- mov a,50h;
- cjne a,#00h,nianfen
- mov a,#01h;
- mov 50h,a;;
- sjmp set2;
- nianfen: cjne a,#01h,naoling;
- mov a,#02h;
- mov 50h,a;
- sjmp set2;
- naoling: cjne a,#02h,maobiao;
- mov a,#03h;
- mov 50h,a;
- sjmp set2;
- maobiao: mov a,#00h;
- mov 50h,a;
- set2: lcall display;
- out: ret;
-
-
- ;**************************************************
- ;函数名:k2
- ;功能: 调整位移位函数
- ;传入参数: 无
- ;传出参数:
- ;**************************************************
- k2: lcall dl30ms;
- jb P0.6,set11;判断是否有键按下
- set10: jnb p0.6,set10;
- lcall chuan;
- mov a,51h;
- cjne a,#00h,zliang
- mov a,#01h;
- mov 51h,a;;
- sjmp set11;
- zliang: cjne a,#01h,gliang;
- mov a,#02h;
- mov 51h,a;
- sjmp set11;
- gliang: cjne a,#02h,bliang;
- mov a,#03h;
- mov 51h,a;
- sjmp set11;
- bliang: cjne a,#03h,set11
- mov a,#00h;
- mov 51h,a;
- set11: lcall display;
- ret;
- ;**************************************************
- ;函数名: jimiao
- ;功能: 计秒程序
- ;传入参数: 无
- ;传出参数: 无
- ;**************************************************
- jimiao: push PSW;
- push acc;
- lcall dl30ms;
- jb p0.4,out5;
- jimao1:jnb p0.4,jimao1;第一次开中断计秒
- mov a,50h;
- cjne a,#03h,out5;
- setb et1;
- setb tr1;
- jimao2:call display;第二次停止
- jb p0.4,jimao2;
- lcall display;
- jb p0.4,out5;
- jimao3:jnb p0.4,jimao3;
- clr tr1;
- clr et1;
- jimao4:call display;第三次清0
- jb p0.4,jimao4;
- lcall display;
- jb p0.4,out5;
- jimao5:jnb p0.4,jimao5;
- mov mao_sfw ,#00h;秒的十分位
- mov mao_bfw ,#00h;秒的百分位
- mov mao_sw,#00h ;秒的十位
- mov mao_gw,#00h ; 秒的各位
- mov mao_qw,#00h;
- mov mao_bw,#00h;
- out5: pop acc;
- pop PSW;
- ljmp start;
- ;;***********************************************
- ;函数名 time1
- ;功能: t1中断函数
- ;传入参数: 无
- ;************************************************
- time1:
- push PSW
- push acc
- mov TL1,#0f0h;
- mov TH1,#0d8h;T1初值为fc18h定时1ms
- mov r1,#mao_bfw;指向秒计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- cjne a,#99h,outT01;当秒到未到达60时跳出中断
- mov 5ah,#00h
- mov 5bh,#00h;将秒清零
- mov r1,#mao_gw;指向分计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- cjne a,#60h,outT01;当分钟未到达60时跳出中断
- mov 5ch,#00h;
- mov 5dh,#00h;
- mov r1,#mao_bw;指向小时计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- cjne a,#60h,outT0;当小时未到达60时跳出中断
- mov 5eh,#00h;
- mov 5fh,#00h;
- outt01:
- pop acc
- pop psw;恢复现场
- reti ;中断返回
- ;**************************************************
- ;函数名: time0
- ;功能: t0中断处理程序函数
- ;传入参数: 无
- ;**************************************************
- time0:
- push PSW
- push acc
- push b ;保护现场
- push 02h
- push 01h
- clr ET0;关T0中断允许
- clr TR0;关T0定时中断
- mov th0,#3ch;
- mov a,#0b0h
- add a,TL0
- mov TL0,a;给定时器重新装值
- setb TR0;允许计时
- djnz r4,outT0;定时没到1s就退出中断
- mov r4,#20;给r0重新赋值
- mov r1,#secH;指向秒计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- cjne a,#60h,outT0;当秒到未到达60时跳出中断
- addmin: ;否则分钟加1
- mov secL,#0
- mov secH,#0;将秒清零
- mov r1,#minH;指向分计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- cjne a,#60h,outT0;当分钟未到达60时跳出中断
- addhour: ;否则小时加1
- mov minL,#0
- mov minH,#0;将分清零
- mov r1,#hourH;指向小时计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- cjne a,#24h,outT0;当小时未到达60时跳出中断
- lcall rili ;调用日历子程序
- outT0:
- pop 01h
- pop 02h
- pop b
- pop acc
- pop psw;恢复现场
- setb ET0;开放中断
- reti ;中断返回
- ;**************************************************
- ;函数名: rili
- ;功能: 日历处理程序函数
- ;传入参数: 无
- ;传出参数:
- ;**************************************************
- rili:
- addday: mov hourL,#0
- mov hourH,#0;将小时清零
- mov r1,#dayH;指向天计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- day31:
- cjne a,#32h,day30;看是不是31号
- ajmp addmon;是的话,加月
- day30:
- mov r5,a
- cjne a,#31h,day29;看是不是30号;是的话,处理
- mov a,#0h
- mov a,monL
- swap a
- orl a,monh;将月份放入a中
- cjne a,#04h,outri;判断是不是4,6,9,11中的某一月
- cjne a,#06h,outri
- cjne a,#09h,outri
- cjne a,#11h,outri;不是的话跳出
- ajmp addmon;是的话,加月
- day29:
- mov a,r5
- cjne a,#30h,day28;看是不是29号
- mov a,#0h
- mov a,monL
- swap a
- orl a,monH
- cjne a,#02h,outri;是的话,看月份是不是2月
- ajmp addmon
- day28:
- mov a,r5
- cjne a,#29h,outri;看是不是28号,不是的话跳出
- mov a,#0h
- mov a,monL
- swap a
- orl a,monH
- cjne a,#02h,outri;看月份是不是2月;是2月,则判断是不是润年
- mov a,#0h
- mov a,yearL
- swap a
- orl a,yearH
- da a
- mov b,#04h
- div ab
- mov r5,b
- cjne r5,#0h,outri
- ajmp addmon
- addmon: ;月加1
- mov dayL,#0
- mov dayH,#0;将天清零
- mov r1,#monH;指向月计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- cjne a,#12h,outri;当月未到达12时
- addyear: ;年加1
- mov monL,#0
- mov monH,#0;将月清零
- mov r1,#yearH;指向年计时单元
- lcall add1;调用加1程序
- mov a,r2;将经过处理的数据放入a中
- outri:
- ret
- ;**************************************************
- ;函数名: add1
- ;功能: 加一函数
- ;传入参数: r1存的是地址指针
- ;r2存的是返回的处理数据
- ;**************************************************
- add1:
- mov a,#0;对a进行清零
- dec r1;指向高四位数据地址
- mov a,@r1;将高四位移入a
- inc r1;指向低四位
- swap a;a中高四位与低四位互换
- orl a,@r1;将低四位显示数据放入a中
- add a,#01h;
- da a;对a中数据进行加1,并作十进制调整
- mov r2,a;将处理后的数据移入r2中,注意r2中存的是十进制对应的bcd码
- mov r3,a;下面是将a中然数据恢复为高位与低位
- anl a,#0f0h;取高四位
- swap a
- dec r1;
- mov @r1,a;将高四位移入低位地址中
- mov a,r3;将暂存数据移回
- anl a,#0fh;取其低四位
- inc r1;指针指向高四位地址
- mov @r1,a;将低四位移到高位地址中
- ret ;子程序返回
- ;**************************************************
- ;函数名: display
- ;功能: 显示处理程序函数
- ;传入参数: 无
- ;传出参数:
- ;**************************************************
- display:mov a,50h;
- cjne a,#00H,dat;00h是时间显示不等则转到年份显示
- timdis: mov r0,#secL;
- sjmp aa
- dat: cjne a,#01h,ala;若为01h则显示年份,否则显示闹钟
- mov r0,#dayL;
- sjmp aa;
- ala: cjne a,#02h,mbiao
- mov r0,#als_l;
- sjmp aa;
- mbiao: mov r0,#mao_sfw;
- nop;
- aa: mov p2,#0ffh;
- mov a,@r0
- mov dptr,#TAB
- movc a,@a+dptr;
- mov p1,a;
- mov a,51h;
- cjne a,#01h,aa01;
- mov a,r4;
- rrc a;
- jnc aa02;
- aa01: mov p2,#0feh;
- aa02: lcall dl5ms;
- lcall dl5ms;
- mov p2,#0FFh;
- inc r0;
- mov a,@r0
- mov dptr,#TAB
- movc a,@a+dptr;
- mov p1,a;
- mov a,51h;
- cjne a,#01h,bb01;
- mov a,r4;
- rrc a;
- jnc bb02;
- bb01: mov p2,#0fdh;
- bb02: lcall dl5ms;
- lcall dl5ms;
- mov p2,#0ffh;
- inc r0;
- mov a,@r0
- mov dptr,#TAB
- movc a,@a+dptr;
- mov p1,a;
- mov a,51h;
- cjne a,#02h,cc01;
- mov a,r4
- rrc a;
- jnc cc02
- cc01: mov p2,#0fbh;
- cc02: lcall dl5ms;
- lcall dl5ms;
- mov p2,#0ffh;
- inc r0;
- mov a,@r0
- mov dptr,#TAB
- movc a,@a+dptr;
- mov p1,a;
- mov a,51h;
- cjne a,#02h,dd01;
- mov a,r4
- rrc a;
- jnc dd02
- dd01: mov p2,#0f7h;
- dd02: lcall dl5ms;
- lcall dl5ms;
- mov p2,#0ffh;
- inc r0;
- mov a,@r0
- mov dptr,#TAB
- movc a,@a+dptr;
- mov p1,a;
- mov a,51h;
- cjne a,#03h,ee01;
- mov a,r4
- rrc a;
- jnc ee02
- ee01: mov p2,#0efh;
- ee02: lcall dl5ms;
- lcall dl5ms;
- mov p2,#0ffh;
- inc r0;
- mov a,@r0
- mov dptr,#TAB
- movc a,@a+dptr;
- mov p1,a;
- mov a,51h;
- cjne a,#03h,ff01;
- mov a,r4
- rrc a;
- jnc ff02
- ff01: mov p2,#0dfh;
- ff02: lcall dl5ms;
- lcall dl5ms;
- ret;
-
- ;;;;;;;;;;;;
- ;延时程序;;;
- ;1ms延时;;;;
- ;;;;;;;;;;;;
- delay1ms:
- mov R6,#14H
- dl1:mov R7,#19H
- dl2:djnz R7,dl2
- djnz R6,dl1
- ret
- dl5ms: mov 55h,#03h;
- d2: mov 56h,#0fh;
- d1: djnz 56h,d1;
- djnz 55h,d2;
- ret;
- dl30ms: lcall dl5ms;
- lcall dl5ms;
- lcall dl5ms;
- lcall dl5ms;
- lcall dl5ms;
- lcall dl5ms;
- ret;
- dl20ms: lcall dl5ms;
- lcall dl5ms;
- lcall dl5ms;
- lcall dl5ms;
- ret;
-
- TAB:DB 0C0H,0f9h,0a4h,0b0h,99h,92h,82h,0f8h,80h,90h;
- end<!--EndFragment-->
复制代码闹钟:
实现闹钟功能主要有两个步骤,首先是能在按键中把闹钟数值写进寄存器,实现存储功能。其次是根据在查询按键服务程序中作判别,检查当前时间是否与闹铃时间相等,如果相等,则使在相应时间时对蜂鸣器提供驱动电流即可。就实现了闹钟设置的功能。
整点报时:
整点报时是在查询按键程序中调用到zhengdi子程序,检查当前的时间是否整点,如果是,则点亮整点指示灯,并响蜂鸣器,停留约2秒钟,自行熄灭与关闭。
按键消抖:
按键消抖可以采用硬件消抖跟软件消抖。我们初定了两种方案:
1是利用数字电路的反相器或斯密特触发器进行整形,如图:
2是采用软件消抖技术
应该说用硬件消抖可以达到更好的效果,不过由于提供的材料跟自身手上的材料没有以上元件,故采用软件消抖。软件的消抖主要是调整出一个切到好处的延迟检测时间,一般为5-30ms。经过我们的多次调试,我们最终得到不错的去抖动效果。在程序中为DMS子程序实现。软件延时是用的最多的消抖方法,但是耗时间。在CPU耗不起时间的情况下,硬件消抖会更好
在本程序中设置了30ms的按键消抖。
感想体会:
本实验花了我们四天的时间,由于该大作业是用汇编语言写的,很多语句掌握都不是很牢固,但是经过这么长时间的实验,我基本掌握了部分汇编语言的用法,特别是实验中经常用到的按键查询,跳转语句,以及汇编的方法。
刚开始的时候,我什麽都不懂,根本不知怎样入门,后来查找了一些系统资料,渐渐有了些了解,才开始写自己的程序。虽然如此,中间还是遇到过不少困难,不如些按键查询的时候,仿真不出来,不知道哪里出错了,也不知道是不是程序有问题,后来在小组成员的帮助下,终于找到问题所在,通过不断的琢磨,后来不仅实现了老师的要求的基本功能,更加了秒表,闹铃还有整点报时。本来还想加上纪念日和音乐闹铃,当一方面时间有限,另一方面尝试后失败了就暂时搁下。
调试的时候,刚上去的时候,板子工作很不稳定,虽然有时候能够显示到正确的东西,当大多数时间都是显示的杂乱无章,鉴于有时候能够正确显示,我们是板子焊的不好,于是重新焊过,第二个版子刚上电的时候,还是不能很正确的工作,后来,一步一步的调试,先用简单的程序检查板子,发现板子是没有问题的,于是就确定是程序的问题,我把程序分为好几块,一块一块的调试,一段好了之后,在加上一段。最后发现是在一个子程序里边用了一个错误的ljmp。 改正了之后就完全正确了。
经过这次试验,确实学到我好多好多的东西。