作者:周锋 来源:网络
(湖北师范学院物理系 湖北 黄石)
摘要:本文介绍了基于单片机的数字钟的设计,详细讨论了它从软件上实现的过程,重点在时钟调整的方式:查询和中断的比较,然后,对数字钟的稳定性和精确性作了相关的讨论。在文章的最后,给出了采用中断方式实现的数字钟的源程序。
关键字:单片机,数字钟,数据缓冲区,中断,定时,消抖
一、引言
在单片机技术日趋成熟的今天,其灵活的硬件电路的设计和软件的设计,让单片机得到了广泛的应用,几乎是从小的电子产品,到大的工业控制,单片机都起到了举足轻重的作用。单片机小的系统结构几乎是所有具有可编程硬件的一个缩影,可谓是“麻雀虽小,肝胆俱全”,单片机的学习和研究是对微机系统学习和研究的简捷途径。
二、 数字钟硬件框图:
三、 程序整体设计:定时模块,显示模块,数据调整模块,状态调整模块。
(1)总体介绍:此部分主要介绍定时模块,和显示模块。定时部分采用经典的定时器定时。它实现了数字钟的主要部分,和秒表的主要部分,以及产生报时信号,定时设置。显示模块是实现数字钟的又一重要部分,其模块的的独立程度直接影响到数字钟的可视化程度。在此部分的设计中,设置专用显示数据缓冲区40h--45h,与分,时及其他数据缓冲区数据区别,在其中存放的是显示段码,而其他缓冲区存放的是时间数据。在显示时,首先将时间十进制数据转化为显示段码,然后送往数码管显示。显示段码采用动态扫描的方式。在要求改变显示数据的类别时,只须改变@R0(指向数据缓冲区的指针)指向的十进制数据缓冲区即可。
(2)数据调整:数据调整有多种方式。一,可以直接进入相关状态进行有关操作,二,将调整分两步,先进入状态,然后执行操作,这两步分别由两个键控制。方式一,比较直接,设计思想也比较简单,但是,这种方式存在操作时间和控制键数目的矛盾。如果用比较少的键,那么可能会在进入状态后处于数据调整等待状态,这样会影响到显示的扫描速度(显示部分可以采用8279芯片来控制,可以解决此问题)。 当然在这种方式下,还可以使用多个状态键,每个状态键,完成一个对应数据的调整。如果采用二的方式,就不会出现这种情况。因为状态的调整,与状态的操作可以分别由两个键控制,其状态的调整数可以多达256个(理论上),操作的完成是这样的,一键控制状态的调整,一键控制数据的调整(具体操作如图2)。以上两种方式的实现都可以采用查询和中断的方式。两种方式必须注意的问题是两者进行相关操作的过程不能太长否则会影响显示的扫描。利用查询的方式,方法传统,对此就不作过多的讨论,以下是采用中断的方式实现的数字钟的一些讨论和有关问题作的一些处理。基于以上的讨论可以设计如下:将调整分为状态调整和数据调整两部分,每次进入中断只执行一次操作,然后返回,这样,就不必让中断处于调整等待状态,这样,可以使中断的耗时很小。将定时器中断的优先级设置为最高级,那么中断的方式和查询的方式一样不会影响到时钟的记数。基于以上的讨论,数据修改的具体操作如下。
在状态进入后,调整指针的指向如右图所示:在右图中@R1表示指向数据缓冲区的指针,它主要是为数据的调整而设立的,在图中:MBF ,HOUR,FS,SS,分别表示时钟的分,时,定时设置分,时,的数据缓冲区。状态5是秒表进入状态,状态6是时钟正常显示状态。 在程序中@R1为专用指针,它的值只在状态调整时改变,每次运行图示模块,只改变一次状态,就跳出程序。调整数据只须改变@R1中的数据即可。
(3)中断方式应注意的问题:
采用中断的方式,最好将定时器中断的优先级设置为最高级,关于程序数据的稳定性应注意两个问题:一,在低优先级中断响应时,应在入栈保护数据时禁止高优先级的中断响应。二,在入栈保护有关数据后,对中断程序执行有影响的状态位,寄存器,必须恢复为复位状态的值。例如,在以下程序中,由于用到了十进制调整,所以在中断进入时,将PSW中的AC,CY位清零,否则,十进制调整出错。
(4)定时准确性的讨论:
程序中定时器,一直处于运行状态,也就是说定时器是理想运作的,其中断程序每隔0.1秒执行一次,在理想状态下,定时器定时是没有系统误差的,但由于定时器中断溢出后,定时器从0开始计数,直到被重新置数,才开始正确定时,这样中断溢出到中断响应到定时器被重新置数,其间消耗的时间就造成了定时器定时的误差。如果在前述定时器不关的情况下,在中断程序的一开始就给定时器置数,此时误差最小,误差大约为:每0.1秒,误差7—12个机器周期。当然这是在定时器定时刚好为0.1秒时的情况,由以上分析,如果数字钟设计为查询的方式或是在中断的方式下将定时器中断设置为最高级,我们在定时值设置时,可以适当的扣除9个机器周期的时间值。但如果在中断的情况下,没有将定时器中断设置为最高级,那就要视中断程序的大小,在定时值设置时,扣除相应的时间值。
(5)软件消抖:
消抖可以采用硬件(施密特触发器)的方式,也可以采用软件的方式。在此只讨论软件方式。软件消抖有定时器定时,和利用延时子程序两种方式。一,定时器定时消抖可以不影响显示模块扫描速度,其实现方法是:设置标志位,在定时器中断中将其置位,然后在程序中查询。将其中断优先级设置为低于时钟定时中断,那么它就可以完全不影响时钟定时。二,在采用延时子程序时,如果显示模块的扫描速度本来就不是很快,此时可能会影响到显示的效果,一般情况下,每秒的扫描次数不应小于50次,否则,数码的显示会出现闪烁的情况。因此,延时子程序的延时时间应该小于20毫秒,如果采用定时器定时的方式,延时时间不影响时钟。
如果,设计时采用的是中断的方式来完成有关操作,同样可以采用软件的方式来消抖,其处理思想是:中断不能连续执行,两次之间有一定的时间间隔。
以下是三种消抖方法的程序流程图:
四、基于以上,设计如下数字钟:
(1)数字钟的操作如下:
按键KEY0
状态1:KEY0=1,数字钟正常时钟显示状态。
状态2:KEY0=2,调整数字钟的分数据。
状态3: KEY0=3, 调整数字钟的时数据。
状态4: KEY0=4,数字钟的定时设置分值。
状态5: KEY0=5,数字钟的定时设置时值。
状态6: KEY0=6,秒表进入状态。
说明:状态N表示KEY0键按下N次。
在进行调整或设置状态时,显示对应状态的数据并且对应的各调整位数码管的DP点亮。这样可以使调整更加可视化。
按键KEY1
完成加一操作,和秒表的清零操作。在进入了时间调整状态或定时设置状态时,按此键可以加一,或在秒表启动后处于停止状态时,按此键可以完成清零操作。
按键KEY3
秒表启动和停止键,此键必须在秒表状态进入了之后才有效。即是:KEY0=6时有效。
定时时间到或整点时,时钟输出报时脉冲。
(2)流程图:
在以下流程图中只描述了基本的功能,象给显示位加点,中断程序状态调整,加一操作,显示状态的切换,在流程图中都没有描述。但其设计就是基于以上介绍的显示指针,和状态指针的思想。在程序中用@R0,@R1充当此指针。程序设计的基本流程图如下:
五、结束语:
本文从整体到部分详细介绍了数字钟的设计,在比较重要的部分进行了详细的论述,并且给出了程序框图及说明。文中在讨论部分隐含的给出了几种数字钟的设计方法,在最后给出了一种采用中断方式设计的数字钟,此方法得到了实验的证明。其可靠性和稳定性都达到了很好的效果。在文中最后给出的设计的基础上很容易扩展写入年月日,其方法基本与时间的显示和调整相类似。
六、参考资料:
[1] 李建忠 编著 ,《单片机原理及应用》.西安电子科技大学出版 2002年2月
[2] 张俊谟 编著 , 《单片机中级教程》.北京航空航天大学出版 2000年1月
附录:
NAME ZF
PORT EQU 0CFA0H
HOUR EQU 26H ;设置数据缓冲区
BUF EQU 23H
SBF EQU 22H
MBF EQU 21H
SA EQU 27H
FA EQU 28H
HH EQU 29H
MB0 EQU 2AH
MB1 EQU 2BH
MB2 EQU 2CH
MM0 EQU 2DH
CSEG AT 0000H
LJMP START ;中断初始化
CSEG AT 0003H
LJMP KEY0
CSEG AT 0013H
LJMP KEY1
CSEG AT 401BH
LJMP CLOCK
CSEG AT 4100H
START: MOV R0, #40H ;数据缓冲区初始化
MOV R6,#00H
MOV A, #00H
MOV @R0, A
INC R0
MOV @R0, A
INC R0
MOV @R0, A
INC R0
MOV @R0, A
INC R0
MOV @R0, A
INC R0
MOV @R0, A
MOV SP, #30H
MOV TMOD, #10H
MOV TH1, #38H
MOV TL1, #00H
MOV BUF, #00H
MOV SBF, #00H
MOV MBF, #00H
MOV HOUR,#00H
MOV SA, #00H
MOV FA, #00H
MOV HH, #00H
MOV MB0, #00H
MOV MB1, #00H
MOV MB2, #00H
MOV MM0, #00H
SETB ET1
SETB EX1
SETB PT1
SETB EA
SETB P3.5
CLR P3.0
MOV TCON, #45H
MOV R5, #01H
DS1: MOV R0, #40H ;扫描显示
MOV R2, #20H
DS2: MOV DPTR, #PORT
MOV A, @R0
ACALL TABLE
CJNE R5, #02 ,L3
SJMP L2
L3: CJNE R5, #04H,L1 ;让调整位的
DP点亮
L2: CJNE R0, #42H,L0
ADD A,#80H
SJMP L0
L1: CJNE R5,#03H, L4
SJMP L5
L4: CJNE R5, #05H,L0
L5: CJNE R0, #44H,L0
ADD A,#80H
L0: MOVX @DPTR, A
MOV A, R2
CPL A
MOV P1, A
MOV R3, #07FH
DEL: NOP
DJNZ R3, DEL
INC R0
CLR C
MOV A, R2
RRC A
MOV R2, A
S2: CJNE R5,#06H,S3 ;切换到显示秒表计数
SETB EX0
SJMP MIAOBIAO
S3: CJNE R5,#04H,S1 ;切换到定时设置状态的显示
SJMP DINGSHI
S1: CJNE R5,#05H,S0
SJMP DINGSHI
S0: JNZ DS2
MOV R0, #40H ;取缓冲区到显示缓冲区
MOV A, SBF
ACALL GET
MOV A, MBF
ACALL GET
MOV A, HOUR
ACALL GET
SJMP DS1
MIAOBIAO:JNZ DS2 ;秒表显示
MOV R0, #40H
MOV A, MB0
ACALL GET
MOV A, MB1
ACALL GET
MOV A, MB2
ACALL GET
AJMP DS1
DINGSHI: JNZ DS2 ; 定时设置显示
MOV R0, #40H
MOV A, HH
ACALL GET
MOV A, FA
ACALL GET
MOV A, SA
ACALL GET
AJMP DS1
TABLE:
INC A ;查表取段码
MOVC A, @A+PC
RET
DB 3FH
DB 06H
DB 5BH
DB 4FH
DB 66H
DB 6DH
DB 7DH
DB 07H
DB 7FH
DB 6FH
DB 40H
GET: ;将一个两位十进制数放入两个数码管对应的两个缓冲区
MOV R4, A
ANL A, #0FH
MOV @R0, A
INC R0
MOV A, R4
SWAP A
ANL A, #0FH
MOV @R0, A
INC R0
RET
CLOCK: ;定时器中断服务程序
JNB P3.0,D4 ;产生定时输出脉冲
CPL P3.4
D4: MOV TL1, #0AFH
MOV TH1, #3CH
PUSH PSW
PUSH ACC
JNB P3.5,C0 ;秒表计数模块
INC MB0
MOV A, MB0
CJNE A, #0AH,C0
MOV MB0, #00H
MOV A, MB1
INC A
DA A
MOV MB1, A
CJNE A, #60H, C0
MOV MB1, #00H
MOV A, MB2
INC A
DA A
MOV MB2, A
CJNE A, #60H, C0
MOV MB2, #00H
C0: JNB 78H, Z1 ;时钟计数程序
INC R6
CJNE R6,#05H,Z1
MOV R6,#00H
CLR 78H
SETB EX0
Z1: JNB 79H, Z2 ;去抖延时程序
INC R6
CJNE R6,#0FH,Z2
MOV R6,#00H
CLR 79H
SETB EX1
Z2: INC BUF
MOV A, BUF
CJNE A, #0AH,QUIT
MOV BUF, #00H
MOV A, SBF
INC A
DA A
MOV SBF, A
CJNE A, #60H, QUIT
MOV SBF, #00H
MOV A, MBF
CLR P3.0 ;定时脉冲输出
一分钟
D2: INC A
DA A
MOV MBF, A
MOV A, FA ;定时比较分值
CJNE A, MBF,D0
SJMP D1
D0: MOV A, MBF
CJNE A, #60H, QUIT
MOV MBF, #00H
MOV A, HOUR
INC A
DA A
MOV HOUR ,A
D1: MOV A,SA ;定时比较时值
CJNE A, HOUR,D3
SETB P3.0
D3: MOV A, HOUR
CJNE A,#18H,QUIT
MOV HOUR,#00H
QUIT: POP ACC
POP PSW
RETI
KEY0: CLR ET1 ;外部中断零服务程序
PUSH ACC
PUSH PSW
SETB ET1
CLR EX0
CLR CY ;清与十进制调整有关的状态位
CLR AC
SETB 78H
JB P3.5,K0
MOV MB0, #00H ; 秒表数据清零
MOV MB1, #00H
MOV MB2, #00H
K0: MOV A,@R1 ;完成加一操作
INC A
DA A
CJNE R1, #26H,K2 ;调整数据的限制
SJMP K3
K2: CJNE R1, #27H,K4
SJMP K3
K4: CJNE A #60H,K1
MOV A,#00H
K3: CJNE A #24H,K1
MOV A,#00H
K1: MOV @R1,A
POP PSW
POP ACC
RETI
KEY1: CLR ET1 ;外部中断一中断程序,完成状态的调整
PUSH ACC
PUSH PSW
SETB ET1
CLR EX1
SETB 79H
CJNE R5,#01H,M0
MOV R1,#21H
INC R5
SETB EX0
SJMP EXIT
M0: CJNE R5,#02H,M1
MOV R1,#26H
INC R5
SETB EX0
SJMP EXIT
M1: CJNE R5,#03H,M2
MOV R1,#28H
INC R5
SETB EX0
SJMP EXIT
M2: CJNE R5,#04H,M3
MOV R1,#27H
INC R5
SETB EX0
SJMP EXIT
M3: CJNE R5,#05H,M4
INC R5
MOV R1,#00H
SETB EX0
SJMP EXIT
M4: CJNE R5,#06H,EXIT
MOV R1,#00H
MOV R5,#01H
CLR EX0
EXIT: SETB EX1
POP PSW
POP ACC
RETI
END