详解:单片机定时器初值的多种计算方式
今天,我们细说一下定时器/计数器的初值的计算。
在讲定时器/计数器之前,首先我们需要了解一下单片机的时钟周期、机器周期、指令周期等这几个周期的区别和其中的关系。
01 机器周期
在传统的51单片机中,一般情况下,1个机器周期=12个时钟周期。在一个单片机最小系统中,如果外接的是12MHZ的晶振,那么机器周期=1微秒。单片机工作时,是一条一条地从ROM中取指令,然后一步一步地执行。单片机访问一次存储器的时间,称之为一个机器周期,这是一个时间基准。
机器周期不仅对于指令执行有着重要的意义,而且机器周期也是单片机定时器和计数器的时间基准。例如一个单片机选择了12MHZ晶振,那么当定时器的数值加1时,实际经过的时间就是1us,这就是单片机的定时原理。
02 12M晶振定时器初值计算
有了以上的概念以后,就可以正确的理解定时器的工作原理了。在传统的51单片机中,通常有个定时器是16位自动重载的模式,我们就以这个工作模式举例。16位的定时器/计数器最大的计数值是65535,当再加1时(=65536),就会发生溢出,产生中断,程序就会自动跳转到定时器/计数器中断函数中去执行中断程序。
前面我们说过,如果单片机最小系统外接的晶振是12M的,那定时计数器加1需要的时间是1us,假如我们需要定时1ms,也就是需要定时计数器加的数值是1000(1000us=1ms),那么初值就是(65536-1000),再把这个值分离出高八位和第八位分别送给TH和TL两个寄存器,这样定时器初值就设置完成了。
前面介绍的定时器初值计算方法采用的晶振是12M,比较好算,如果是其它的晶振频率,就用12去除好了。比如是6M的,那么就是12/6=2,每个计数是2us,那么你要定时1ms就只要计数500个即可以;24M的晶振,就是12/24=0.5,每个计数周期是0.5us,需要定时1ms就需要计数2000。
03 通用晶振频率定时器初值计算
在更多的使用场景下,我们用的晶振频率不一定是12的倍数。这种情况下,再用上面的计算方法显然是不好计算初值的。那么又该怎么计算初值呢?
为了解决这个问题,我们来想一件事情,那就是24M的晶振,它实际就是在1s时间内产生了24000000个脉冲信号(时钟周期),传统51单片机需要12个脉冲信号才能完成一次寄存器的读写,定时器的计数加1也是需要相同的时间(12个脉冲信号),也就是机器周期。
这样一来,是不是可以得到1s内定时器可以计数的次数是(24000000/12)个;1ms内定时器可以计数的次数是(24000000/12/1000)次;1us内定时器可以计数的次数是(24000000/12/1000/1000)次。
大家注意观察,以上算式中的24000000其实就是24M晶振1s内产生的脉冲次数,其实就是当前晶振频率下的周期数。这样一来如果希望定时1ms的时间,初值就是计数最大值65536减去定时器1ms时间内可以计数的次数(24000000/12/1000),初值=65536-(24000000/12/1000)=65536-2000。
大家会发现,计算出来的结果和传统方法计算的结果是相同的,再一次验证了这种计算方法的正确性。
那么,推导出通用晶振频率下1ms定时的初值计算公式可以写成:初值=65536-(FOSC/12/1000),其中FOSC是晶振频率对应的周期数。
这样一来,就不用再考虑频率是否是12的倍数关系了。但需要注意的是,以上计算方式需要定时器工作在16位模式,计算得到的结果是一个16位的数,需要分离出高八位和第八位分别赋值给TH和TL和寄存器。
04 STC单片机的1T/12T模式
说到这里,大家应该对定时器初值的计算没有问题了,那么我们来看一下STC官方给出的定时器的示例程序。
大家会发现,STC官方例程采用的就是我们上面推到的方法,在上面的例程中,用的晶振频率是18.432M,如果按照传统方式去计算初值将会很难计算。
通过前面的推到公式,结合STC官方例程,自然就能理解STC官方说的定时器工作在1T模式和12T模式了。也就是在1T模式下,定时器将会更快,一个时钟周期就是一个机器周期,而在12T模式下,就和传统51单片机一样,12个时钟周期才是一个机器周期。
通常情况下,定时器的中断频率不能太快,太快会打乱正常程序的运行节奏,程序效率会降低,所以在更多的使用场景下,小代还是喜欢把定时器设置为12T模式下工作。但是,在1T模式下可以实现定时的时间更加精确,在12M晶振频率下,又把1us,做了12次的细分。实际应用时还是看各位小伙伴的习惯和具体的运用场景。
05 为什么是定时/计数器
细心的小伙伴肯定会发现一个问题,几乎在所有的单片机教程或资料中,说到定时器,肯定是会写成定时器/计数器,大家都常常叫做定时计数器,那到底是定时器呢,还是计数器呢,还是就是定时计数器呢?
标准的叫法,其实应该是计数器。定时计数器其实质就是一个自动向上累加的一个累加器,通过累加器实现记录次数的功能,只是说在定时器模式下,记录的每次累加的次数的时间是固定的,比如前面我们计算的,12M晶振下,每累加1次,时间是1us;在计数模式下,记录的累加次数之间的时间间隔是不定的,累加次数的信号通常情况下是外部的脉冲信号。
每次一次累加的时间间隔固定,那通过累加次数程序固定的间隔时间,就是定时的时间,每一次累加的时间间隔不定,不等常,那自然只能得到累加的次数。这就是定时器和计数器的实际工作原理。所以说,准确的表示应该叫计数器,因为它只能实现计数的功能。
说了那么多,再来看STC公布的这个定时器/计数器的结构图就很清楚了。
当C/T=0时,多路开关连接到系统时钟上,系统时钟通过分频(1T或12T)连接到定时器/计数器的累加器上,定时器/计数器对系统时钟进行计数,因为系统时钟频率是固定的,通过记录次数可以计算得到时间,所以此时定时器/计数器工作在定时模式,是定时器。
当C/T=1是,多路开关连接到外部脉冲输入引脚上,此时引脚上的脉冲信号的周期不定,所以没办法通过记录次数计算得到时间,此时定时器/计数器工作在计数模式,是计数器。
来源:单片机技术宅
|