单片机定时中断的精确定时编程方法种种
引言 MCS-51 单片机的中断响应延迟时间,取决于其它中断服务程序是否在进行,或取决于正在执行的是什么样的指令。单中断系统中的中断响应时间为 3~8 个机器周期[1]。无论是哪一种原因引起的误差,在精确定时的应用场合,必须考虑它们的影响,以确保精确的定时控制。根据定时中断的不同应用情况,应选择不同的精确定时编程方法。 文中以定时器 T1 工作在定时方式 1 为例,晶振频率为 12MHz。1 方法 1 在定时器溢出中断得到响应时,停止定时器计数,读出计数值(反映了中断响应的延迟时间),根据此计数值算出到下一次中断时,需多长时间,由此来重装载和启动定时器。
例如定时周期为 1ms,则通常定时器重装载值为-1000(0FC18H)。下面的程序在计算每个定时周期的精确重装载值时,考虑了由停止计数(CLR TR1)到重新启动计数(SETB TR1)之间的 7 个机器周期时间。程序中#LOW(-1000+7)和#HIGH(-1000+7)是汇编符号,分别表示-1000+7=0FC1FH 这个立即数的低位字节(1FH)和高位字节(0FCH)。……CLR EA;禁止所有中断 CLR TR1;停止定时器 T1MOV A,#LOW(-1000+7);期望数的低位字节 ADD A,TL1;进行修正 MOV TL1,A;重装载低位字节 MOV A,#HIGH(-1000+7);对高位字节处理 ADDC A,TH1 MOV TH1,A SETB TR1;重启动定时器 SETB EA;重开中断…… 此方法适用于各种原因造成的定时误差的情况,为通用方法。
2 方法 2 假如定时周期为 10ms,通常定时器重装载值为 0D8F0H,中断子程序如下[2]:ORL TL1,#0F0HMOV TH1,#0D8H…… 这里用 ORL TL1,#0F0H 代替 MOV TL1,#0F0H 可提高定时精度。此方法只适用于重装载值低位字节的低 4 位为零,且中断响应的延迟时间小于 16 个机器周期的情况。类似的定时器重装载值有 0FFF0H,0FFE0H 等。3 方法 3 假如定时周期为 1ms,通常定时器重装载值为 0FC18H,中断子程序如下:MOV A,#LOW(-1000+4);期望数的低位字节 ADD A,TL1MOV TL1,AMOV A,#HIGH(-1000+4);对高位字节处理 ADDC A,TH1MOV TH1,ADEC TL1;恢复提前了的 2 个机器周期…… 这种方法中不停止定时器计数过程,若在执行指令 ADDC A,TH1 或 MOV TH1,A 时,恰好产生 TL1 溢出向 TH1 进位的情况,则 TH1 的值就不对了,会产生更大的误差。
为此,程序段开头为重装载值加 4,若有溢出进位,则可提前发生,其中 2 个机器周期是考虑到为 TL1 重装载占用的时间。 此方法适用于系统中无其它更高优先级中断源的情况。若类似方法 1,在程序段开头和结尾分别加上禁止所有中断(CLR EA)和开中断(SETB EA)指令,则将适用于所有情况。4 方法 4 假如定时周期不确定,只知道定时器重装载值存放在寄存器 R3、R2 中,中断子程序如下:MOV A,#05H;3 个机器周期装载 TL1,2 个周期提前 ADD A,TL1 ADD A,R2MOV TL1,A MOV A,R3;处理高位字节 ADDC A,TH1MOV TH1,ADEC TL1;恢复提前了的 2 个机器周期…… 此法适用于定时周期不确定的情况,其它同方法 3。
5 方法 5 当定时中断发生的位置可预知时,通常出现在主程序的 AJMP $ (或 SJMP $)等待指令处,中断延迟时间为 3 个或 4 个机器周期。取固定值 4 可简化补偿程序。以定时周期 1ms 为例,中断子程序如下:ORG 001BHMOV TL1,#LOW(-1000+4)MOV TH1,#HIGH(-1000+4)…… 此方法适用于定时中断总发生在同一条指令位置,且无其它中断源的情况。结语 上述 5 种方法误差均不超过 1 个机器周期,其中方法 1、3、4 较为通用,适用于任何情况,但程序较长;方法 2、5 简单,但必须注意满足对应条件,才能使用。
当然,也还有其它方法[3],但比较烦琐,并不理想,这里不一一介绍。