资源描述
毕业设计:基于单片机的电子日历时钟(完整版)资料
(可以直接使用,可编辑 优秀版资料,欢迎下载)
一 课程设计题目: 电子日历时钟
二 实现的功能:
基本功能:
(1) 显示北京时间,并且能够校准时间;
(2) 程序使用汇编语言;
(3) 显示的时、分、秒之间以及年、月、日间以小数点分隔;
(4) 显示公历日期,并且能够校准日期;
发挥功能:
(5) 运动秒表;
(6) 闹钟功能;
(7) 自动整点报时。
三 课程设计的目的:
课程标志性内容的设计理解和综合运用,对所学内容进行一次实操,学以致用。
四、设计方案说明
1、硬件部分
(1) 采用6位LED数码管显示日期或者时间。
(2) 显示器的驱动采用 “动态扫描驱动”, 且采用“一键多用”的设计方案,系统电路大为简化。使用小数点表示闹钟设置状态;
(3) 电路连接使用PCB,使电路连接简洁美观
2、软件部分
(1) “时钟”基准时间由单片机内部的定时中断提供,考虑因素:定时时间是“秒”的整除数,且长短适宜。最长不能超过16位定时器的最长定时时间;最短不能少于中断服务程序的执行时间。基准时间越短,越有利于提高时钟的运行精确度。基准时间定为0.05秒。
(2) 用一个计数器对定时中断的次数进行计数,由基准时间为0.05秒知计数值为20即可实现实现“秒”定时,同理进行“分”﹑“时”定时,以及“日”﹑“月”﹑“年”定时。
(3) LED 数码管显示器采用“动态扫描驱动”考虑问题:驱动信号的维持时间必须大于“起辉时间”(电流大起辉时间短),而驱动信号的间歇时间必须小于“余辉时间”(电流大余辉时间长),但驱动电流大小受硬件电路能力和LED数码管极限功耗的制约。
(4) 动态扫描显示方式在更新显示内容时,考虑到因LED数码管余辉的存在可能会造成显示字符的模糊,所以新内容写入显示器之前将所有的LED数码管熄灭。
(5) 关于自动识别“月大﹑月小”和“平年﹑润年”问题的考虑
a) 月大和月小
2月另外计算;
4月﹑6月﹑9月﹑11 月为月小30天,其余为月大31天。
b) 平年和润年(年号能被4整除的就是润年)
平年的2月为28天;
润年的2月为29天。
五、使用说明
实物图请参照后面附带图片,从左至右为按键K2,K1,K0,以两个LED显示器为一组,左中右显示时分秒或者年月日,还有闹钟和秒表
K2:复位 K1:设置闪烁 K0:切换时间/日期或者调整时间/日期
初始状态:接上电源之后,日期默认为10年6月21日,时间为0时0分
秒,闹钟2点整但默认关闭,秒表为0状态
(1)显示状态切换:不断按K0键就会依次循环显示下面的状态
初始状态时间
日期
闹钟时间
闹钟状态
秒表状态
(2)调节时间,日期:按K0键切换到想要调节的显示状态,再按K1键选择要修改的位,不断按K1键会按左闪烁.中闪烁.右闪烁.确定.四个状态切换,闪烁的位可以修改,按K0键可以实现增加,不能递减,例如要调慢时间要按到循环到较慢时间。
(3)闹钟使用:闹钟默认响的时间为一分钟,闹钟的时间设置同时间日期的调节,只需把状态切换到闹钟时间的状态,闹钟的开关先按K0键切换到屏幕显示为OFF的状态,如下:
再按K1可切换到开状态,如下图,再按K1可关闭,不断循环
(4) 秒表:K0键按4下就可切换到秒表状态,出示为0,此时按下K1键就可开始计时,再按一下K1键可停止,此时K1为秒表开关,按K0键可再切换显示其他。
六、硬件连接图
1、原理图
2、pcb图
3、实物图
七、程序流程图:
1. 主程序
主程序
系统初始化
整点?
闹钟到?
提示音
闹铃提示音
N
N
Y
Y
2. 定时器0中断子程序
定时器0中断子程序
保护现场
重载计数初值
秒表?
秒表模块
到1秒?
秒加1或向前进位
恢复现场
中断返回
Y
Y
N
N
3. 外部中断0子程序
外部INT0中断
带显示延时消抖
调整模式
有闪烁?
切换显示模式
时间调整
调整时间?
调整日期?
调整闹钟?
日期调整
秒表模式?
日期、闹钟、闹钟设置、秒表显示循环切换
闹钟调整
进入秒表
中断退出
Y
N
N
Y
Y
N
N
N
Y
Y
Y
Y
保护Psw、A寄存器
恢复psw、A寄存器
初始化秒表
后台计时?
Y
N
N
提示音滴
Key1按下?
4. 外部中断1子程序
外部INT1中断
保护psw、A寄存器
带显示延时
Key0按下?
秒表模式?
设置闹钟?
暂停/继续计时
打开/关闭闹钟
闪烁循环切换
滴一声提示
闪烁切换模式
恢复psw、A寄存器
退出中断
Y
Y
Y
N
N
N
八、性能测试与故障排查
1、硬件部分
问题:断路。
现象:程序下载完之后可以工作但是6个LED显示器有2个没亮。
分析:因为其他几个显示器完全正常,这两个则完全没亮,所以推断是位选的线路出故障。
检测:用万用表测试各点电压,着重测试两条位选线路的断路与短路情况,最终发现两处断路。
解决:焊锡接上,最终全亮
2、软件部分
偶数组实现基础功能的程序老师已经提供,该程序基本没有多大的问题,就是里面的几个参数需要修改,同时还有一个小bug。
修改一:由于提供的程序所默认采取的晶振计数频率是6MHz,但是所提供的现实原件则是12MHz,所以根据晶振的不同,定时器的定时时间变为0.05s。按照该程序直接跑的话,计数时间为0.5s。这就需要设置计数次数TICK_CNT为#14H,即0.05s*20=1s。代码段:MOV TICK_CNT,#14H
修改二:程序默认设置的外部中断延时过短,导致操作过于“灵敏”,也即按键K0、K1按下时,跳变过快。这里所说的延时是中断子程序EX0_INT和EX1_INT中的语句
LCALL DIS_DELAY。解决这个情况只需修改DELAY 次数,则DIS_DELAY:
MOV D_CNT_DIS,#10H。
修改三:观察实物电路工作发现每一位:LED数码管的小数点都是亮的,没有起到用小数点区分时间/日期中的时分秒/年月日。要解决这个问题,在显示子程序中TSA代码段的MOV Rx A前插入语句ADD A,#80H(x=1、2、4、6)。
以及加上发挥部分的拓展功能:秒表和闹钟。
九、原件清单
品名
型号
数量
LED七段数码管
共阳BS
6
三极管
S8550
7
电阻
3k
8
电阻
200Ω
9
电阻
4.7k
1
微型按钮
4脚
3
瓷片电容
30p
2
电解电容
10uf
1
晶体振荡器
12MHz
1
小型蜂鸣器
自发声
1
排针
无
6
IC
AT89S52
1
IC
74LS244
1
IC座
40脚
1
IC座
20脚
1
十、心得体会与总结
这个学期做了两个与汇编有关的课程设计(不过这次是大作业),一次是开学初的微机原理课程设计,还有就是这次单片机原理大作业。上次基本上只与程序打交道,硬件部分实操不多。而这次大作业则是硬件、软件两方面都有兼顾,且两者所花的时间也都不少。虽然从老师那已经获取了原理图和程序,但这是我们第一次比较系统的从熟悉软件操作到软硬件设计了解整个流程。
硬件部分,由于先前我们都没有操作过protel之类的软件,所以一切从零开始,针对这次大作业需要,学习了protel软件的基本操作、原理图的绘制修改、原件的封装以及原件集成库的创建,当然还有PCB板的排线。之后就是PCB图打印,电路板热压制、腐蚀、钻孔,元器件的焊接。流程很简洁,过程很纠结。我们一步一个脚印地制作着,生怕哪个步骤出错而导致前功尽废。不过在我们不懈努力下终于走完。但是焊接的不仔细——两个电阻虚焊,使后来电路出现问题,也排查了好久,需要记住教训。
软件部分,虽然老师已经给了具备基本功能的程序,但是仍需看懂弄懂,后期才能更好地发现问题以及修改添加功能。我发现这个过程也并非一件易事,清楚认识每一句的作用也需要经常查阅书籍。另外在硬件焊接已经实现后我们把两者结合在一起,通过下载器把程序烧进52单片机中实现既定功能,发现上面故障排查中出现的问题,继而针对每个问题分别从软硬件寻找解决方法,这个过程我认为收获更大,能让我们更清楚熟悉软硬件两者的运作方法。
而且我俩分工是按硬件、软件而分的,自个儿认为分工尚算明确,各司其职。
十一、程序附录
;wahaha.asm
; (Electronic Calendar and Clock)
; Key0(for shift/adjust) connected to INT1
; Key1(for un-flash/flash) connected to INT0
; 学生姓名:陈晓伟、冯劲增
; 学生学号:2,2
; 分组编号:004
;变量定义
TICK_CNT EQU 20H ;T0倍乘
;------------------
SECOND_BCD EQU 21H ;时间记录
MINUTE_BCD EQU 22H
HOUR_BCD EQU 23H
DAY_BCD EQU 24H ;日期记录
MONTH_BCD EQU 25H
YEAR_BCD EQU 26H
;------------------
FLASH_FLAG EQU 27H ;是否闪烁
DIS_FLAG EQU R7 ;当前显示内容标志 ;DIS_FLAG: 0-时间;1-日期;2-闹钟;3-闹钟开关;4-秒表
;------------------
NSECOND_BCD EQU 2BH ;闹钟时间
NMINUTE_BCD EQU 2CH
NHOUR_BCD EQU 2DH
;------------------
TCC_BCD EQU 2EH ;秒表计时器
TBB_BCD EQU 2FH
TAA_BCD EQU 30H
;------------------
TIMER_FLAG EQU 31H ;秒表模式
TIMER_START_FLAG EQU 32H ;秒表开始
;------------------
ALAM_STATE EQU 33H ;闹钟开启标志
;------------------
DI_40H EQU 34H ;提示音延时变量
DI_41H EQU 35H ;延时
;------------------
ALAM_ON1 EQU 36H ;闹钟状态显示
ALAM_ON2 EQU 37H
ALAM_ON3 EQU 38H
ALAM_OFF1 EQU 39H
ALAM_OFF2 EQU 3AH
ALAM_OFF3 EQU 3BH
;------------------
;中断向量表
ORG 0000H
LJMP MAIN
ORG 0003H
LJMP EX0_INT ; port INT0
ORG 000BH
LJMP T0_INT ; port T0
ORG 0013H
LJMP EX1_INT ; port INT1
;主程序
ORG 0030H
MAIN: NOP ; main program
;初始化堆栈
MOV SP,#60H
;初始化变量
MOV SECOND_BCD,#00H ; BCD of "second"
MOV MINUTE_BCD,#00H ; BCD of "minute"
MOV HOUR_BCD,#00H ; BCD of "hour"
MOV NSECOND_BCD,#00H ;闹钟BCD of "second"
MOV NMINUTE_BCD,#00H ;闹钟 BCD of "minute"
MOV NHOUR_BCD,#06H ;闹钟BCD of "hour"
MOV TCC_BCD,#00H ; 秒表BCD of "second"
MOV TBB_BCD,#00H ; 秒表BCD of "minute"
MOV TAA_BCD,#00H ; 秒表BCD of "hour"
MOV TIMER_START_FLAG,#00H ;秒表工作标志
MOV TIMER_FLAG,#00H ;秒表模式标志
MOV DAY_BCD,#21H ; BCD of "day"
MOV MONTH_BCD,#06H ; BCD of "month"
MOV YEAR_BCD,#010H ; BCD of "year"
MOV FLASH_FLAG,#00H ; flag for un-flash/flash
MOV DIS_FLAG,#00H ; flag for shift(time/date)
MOV ALAM_ON1,#55H ; BCD OFF 闹钟状态显示
MOV ALAM_ON2,#01H
MOV ALAM_ON3,#55H
MOV ALAM_OFF1,#63H
MOV ALAM_OFF2,#42H
MOV ALAM_OFF3,#33H
MOV ALAM_STATE,#00H ;初始化闹钟状态为OFF
;------------------
MOV TL0,#0B0H ; constant for 0.05s
MOV TH0,#3CH ; 65536-15536=50,000 for 12MHz
MOV TICK_CNT,#14H ; times of overflow 0.05*20=1s
MOV TMOD,#01H ; Mode 1 for T0, Timer Mode
SETB ET0 ; open T0
SETB EX0 ; open INT0, Key1
SETB EX1 ; open INT1, Key0
SETB EA ; total open
SETB PT0 ; priority for T0,高优先级
SETB TR0 ; start T0, Run
SCAN_HOUR: ;闹钟扫描
MOV A,SECOND_BCD
CJNE A,#00H,SCANALARM
MOV A,MINUTE_BCD
CJNE A,#00H,SCANALARM
HOUR:
CLR P2.0
NOP ;整点,滴
SETB P2.0
SCANALARM: ;闹钟扫描
MOV A,ALAM_STATE
JZ SCAN_HOUR ;闹钟开关已打开?
MOV A,NHOUR_BCD
CJNE A,HOUR_BCD,WAIT
MOV A,NMINUTE_BCD
CJNE A,MINUTE_BCD,WAIT
ALARM:
CLR P2.0 ;闹铃:滴滴滴滴``````
SETB P2.0
CLR P2.0
SETB P2.0
CLR P2.0
SETB P2.0
CLR P2.0
SETB P2.0
NOP
NOP
NOP
WAIT:
SETB P2.0
SJMP SCAN_HOUR ; wait for interrupt
; -------------------------------------------------
; sub: T0 interrupt
; 定时器0中断
T0_INT:
PUSH ACC
MOV TL0,#0B0H ; constant for 0.05s
MOV TH0,#3CH ; Timer 0重装载
MOV A,TIMER_START_FLAG
CJNE A,#01H,TIMER_NEXT ;秒表模式?
LJMP TIMER_INC ;秒表计时
TIMER_NEXT:
DJNZ TICK_CNT,NOT_1S ; is up to 1 second ?
SJMP IS_1S
NOT_1S:
LJMP T0_RET
; 1秒时间到
IS_1S:
MOV A,SECOND_BCD ; take BCD of "second"
CJNE A,#59H,IN3 ; is up to 59 seconds ?
SJMP IN4
IN3:LJMP SECOND_INC ; 秒加1
IN4:MOV SECOND_BCD,#00H ; 秒进位
MOV A,MINUTE_BCD ; take BCD of "minute"
CJNE A,#59H,IN5 ; is up to 59 minutes ?
SJMP IN6
IN5: LJMP MINUTE_INC
IN6: MOV MINUTE_BCD,#00H ; 分进位
MOV A,HOUR_BCD ; take BCD of "hour"
CJNE A,#23H,HOUR_INC ; is up to 23 hours ?
MOV HOUR_BCD,#00H ; "时"进位
MOV A,MONTH_BCD ; take BCD of "month"
CJNE A,#02H,NOT_FEB ; is February ?
;2月处理
;--------------------------
FEB: NOP
ACALL BCD_DIV4 ; BCD of "year in 26H" divided by 4
MOV A,R3 ; remainder in R3
CJNE A,#00H,NOT_LEAP_Y ; "00" means leap year
;闰年,29天
LEAP_Y: MOV A,DAY_BCD ; take BCD of "day" in Feb.
CJNE A,#29H,DAY_INC ; is up to 29 days (leap year)?
MOV DAY_BCD,#01H ; keep the first day
MOV MONTH_BCD,#03H ; increase "month"
SJMP RESET_CNT
;非闰年
NOT_LEAP_Y: MOV A,DAY_BCD ; take BCD of "day" in Feb.
CJNE A,#28H,DAY_INC ; is up to 28 days (common year)?
MOV DAY_BCD,#01H ; keep the first day
MOV MONTH_BCD,#03H ; increase "month"
SJMP RESET_CNT
;---------------------------
;非2月处理
;30/31天?
NOT_FEB:NOP ; other "month" except Feb.
CJNE A,#04H,Y01 ; is April ?
AJMP MON_30D
Y01: CJNE A,#06H,Y02 ; is June ?
AJMP MON_30D
Y02: CJNE A,#09H,Y03 ; is September ?
AJMP MON_30D
Y03: CJNE A,#11H,T11 ; is November ?
AJMP MON_30D
;31天
T11: MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#31H,DAY_INC ; is up to 31 days ?
AJMP NEXT_MONTH
;30天
MON_30D:MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#30H,DAY_INC ; is up to 30 days ?
;天进位
NEXT_MONTH: MOV DAY_BCD,#01H ; keep the first day
MOV A,MONTH_BCD ; take BCD of "month"
CJNE A,#12H,MONTH_INC ; is December ?
; 月进位
MOV MONTH_BCD,#01H ; keep the first month
MOV A,YEAR_BCD ; take BCD of "year"
CJNE A,#99H,YEAR_INC ; is up to 99 years ?
MOV YEAR_BCD,#00H ; keep the first year
SJMP RESET_CNT
;年加1
YEAR_INC: MOV A,YEAR_BCD ; take BCD of "year"
ADD A,#01H ; increase "year"
DA A ; adjust BCD
MOV YEAR_BCD,A ; keep "year"
SJMP RESET_CNT
MONTH_INC: MOV A,MONTH_BCD ; take BCD of "month"
ADD A,#01H ; increase "month"
DA A ; BCD码调整
MOV MONTH_BCD,A ; keep "month"
SJMP RESET_CNT
DAY_INC: MOV A,DAY_BCD ; take BCD of "day"
ADD A,#01H ; increase "day"
DA A ; BCD码调整
MOV DAY_BCD,A ; keep "day"
SJMP RESET_CNT
HOUR_INC: MOV A,HOUR_BCD ; take BCD of "hour"
ADD A,#01H ; increase "hour"
DA A ; BCD码调整
MOV HOUR_BCD,A ; keep "hour"
SJMP RESET_CNT
MINUTE_INC: MOV A,MINUTE_BCD ; take BCD of "minute"
ADD A,#01H ; increase "minute"
DA A ; BCD码调整
MOV MINUTE_BCD,A ; keep "minute"
SJMP RESET_CNT
SECOND_INC: MOV A,SECOND_BCD ; take BCD of "second"
ADD A,#01H ; increase "second"
DA A ; BCD码调整
MOV SECOND_BCD,A ; save back "second"
RESET_CNT: MOV TICK_CNT,#14H ; retrieve times of overflow
T0_RET:
POP ACC
RETI
;--------------------------------------------------------------------
;秒表增
TIMER_INC:
TCC_INC:
MOV A,TCC_BCD ; take BCD of "0.05S"
CLR C
SUBB A,#95H
JZ TBB_INC
MOV A,TCC_BCD
ADD A,#05H ; increase "0.05S"
DA A ; BCD码调整
MOV TCC_BCD,A ; keep "0.05S"
AJMP TIMER_OUT
TBB_INC:
MOV TCC_BCD,#00H
MOV A,TBB_BCD ; take BCD of "SECOND"
CLR C
SUBB A,#59H
JZ TAA_INC
MOV A,TBB_BCD
ADD A,#01H ; increase "SECOND"
DA A ; BCD码调整
MOV TBB_BCD,A ; keep "SECOND"
AJMP TIMER_OUT
TAA_INC:
MOV TBB_BCD,#00H
MOV A,TAA_BCD ; take BCD of "MINUTE"
CLR C
SUBB A,#59H
JZ TDD_INC
MOV A,TAA_BCD
ADD A,#01H ; increase "MINUTE"
DA A ; BCD码调整
MOV TAA_BCD,A ; save back "MINUTE"
AJMP TIMER_OUT
TDD_INC:MOV TAA_BCD,00H
TIMER_OUT: LJMP TIMER_NEXT ;返回定时器中断
;------------------------------------------------------------------
; -------------------------------------------------------------------
; sub: LED Display
;显示子程序
DISPLAY:
MOV A,DIS_FLAG
CJNE A,#03H,DISPLAY2 ;选择不同字模
MOV DPTR,#TAB2
SJMP DISPLAY3
DISPLAY2:
MOV DPTR,#TAB ; set address of code table
DISPLAY3:
MOV A,DIS_FLAG ; take flag for shift
CJNE A,#00H,DISP_DATE ; "00" 当前显示内容为时间
;R0: point to display buffer
DISP_TIME: MOV R0,#SECOND_BCD ; beginning from "second"
SJMP TSA
DISP_DATE:
CJNE A,#01H,DISP_ALAM ; "01" 当前显示内容为日期
MOV R0,#DAY_BCD ; "FF" for showing date
SJMP TSA;显示时间或日期
DISP_ALAM:
CJNE A,#02H,DISP_ALAM_SET ; "02" 当前显示内容为闹钟
MOV R0,#NSECOND_BCD ; beginning from "second"
SJMP TSA
DISP_ALAM_SET:
CJNE A,#03H,DISP_TIMER ; "03" 当前显示内容为闹钟设置
MOV A,ALAM_STATE ; 闹钟状态显示
JZ SHOWOFF
MOV R0,#ALAM_ON1 ; 显示"ON"
SJMP TSA
SHOWOFF:
MOV R0,#ALAM_OFF1 ;显示"OFF"
SJMP TSA
DISP_TIMER: ;"04"当前显示内容为秒表
MOV R0,#TCC_BCD ; beginning from "second"
TSA: MOV A,@R0 ; begin from "day"
ANL A,#0FH ; get the "low half byte"
MOVC A,@A+DPTR ; take character from code table
MOV R1,A ; keep in R1 for DS6 showing
MOV A,@R0
SWAP A
ANL A,#0FH ; get the "high half byte"
MOVC A,@A+DPTR ; take character from code table
MOV R2,A ; keep in R2 for DS5 showing
;---------------
INC R0
MOV A,@R0 ; next one from "month"
ANL A,#0FH ; get the "low half byte"
MOVC A,@A+DPTR
MOV R3,A ; keep in R3 for DS4 showing
MOV A,@R0
SWAP A
ANL A,#0FH ; get the "high half byte"
MOVC A,@A+DPTR
MOV R4,A ; keep in R4 for DS3 showing
;-------------
INC R0
MOV A,@R0 ; next one from "year"
ANL A,#0FH ; get the "low half byte"
MOVC A,@A+DPTR
MOV R5,A ; keep in R5 for DS2 showing
MOV A,@R0
SWAP A
ANL A,#0FH ; get the "high half byte"
MOVC A,@A+DPTR
MOV R6,A ; keep in R6 for DS1 showing
;---------------------
;P1:位选线
;P0:段选线
NOP
TDP: MOV P1,#0FFH ; close all showing///
;Display DS6
MOV A,ALAM_STATE ;是否显示闹钟状态位?(最末位小数点)
JZ DIS_NEXT
MOV A,R1
ANL A,#7FH
MOV R1,A
DIS_NEXT:
MOV A,R1
MOV P0,A ; send character to DS6
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#03H,A02 ; "03" is flash on DS5&DS6
SJMP A03
A02: CJNE A,#03H,A04; ; "03" is flash on DS5&DS6
A03: MOV A,TICK_CNT ; take Counter of overflow
RRC A
JNC A05 ; check bit C ( 1 or 0 )
A04: MOV P1,#0dfH ; turn on DS6
A05: LCALL DELAY
MOV P1,#0FFH ; close all showing
;Display DS5
MOV P0,R2 ; send character to DS5
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#03H,B02 ; "03" is flash on DS5&DS6
SJMP B03
B02: CJNE A,#03H,B04
B03: MOV A,TICK_CNT ; take times of overflow
RRC A
JNC B05 ; check bit C ( 1 or 0 )
B04: MOV P1,#0efH ; turn on DS5
B05: LCALL DELAY
MOV P1,#0FFH ; close all showing
;Display DS4
MOV A,R3
ANL A,#7FH ;该位增加小数点显示
MOV P0,A ; send character to DS4
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#02H,C02 ; "02" is flash on DS3&DS4
SJMP C03
C02: CJNE A,#02H,C04
C03: MOV A,TICK_CNT ; take times of overflow
RRC A
JNC C05 ; check bit C ( 1 or 0 )
C04: MOV P1,#0f7H ; turn on DS4
C05: LCALL DELAY
MOV P1,#0FFH ; close all showing
;Display DS3
MOV P0,R4 ; send character to DS3
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#02H,D02 ; "02" is flash on DS3&DS4
SJMP D03
D02: CJNE A,#02H,D04
D03: MOV A,TICK_CNT ; take times of overflow
展开阅读全文