控制/MCU
【C51】单片机定时器介绍
标准51架构的单片机有2个定时器 :T0 和 T1,他们2个的用法几乎一样。下面主要讲T0定时器的用法。
初步认知定时器 和 计数器 都是单片机中同一个模块。他们的实质都是: 加法存储计数器。对于计数器很好理解,每来一个信号(信号从P3.4 或者P3.5输入),就加1,以此达到计数的目的。
对于定时器,每隔1个机器周期 加 1,假如(只是假如)一个机器周期为 1ms , 当加到1000时,我们就认为经过了1s,这就是定时器的原理。
加法存储寄存器THx & TLx
定时器依赖计数,需要把累计增加的那个量存储在某个地方,这就是THx和TLx(x 可以是 0 或者1)2个8位寄存器的的职责。
T0和T1都拥有一对加法存储寄存器。
T0 对应:TH0,TL0
T1 对应 : TH1 , TL1
在reg51.h头文件中我们发现这4个寄存器的定义:
sfr TL0 = 0x8A; // TL中的L是LOW的意思,代表低位,同理H代表HIGH高位。 sfr TL1 = 0x8B; sfr TH0 = 0x8C; sfr TH1 = 0x8D;
他们可以在程序中直接使用,复位值都是 0 。
当一直累加,使得他们保存不了太大的数据而发生溢出时,就会引发中断(后面讲中断)。并且对应的TFx溢出标志位会置为1,(没有溢出的情况下是0)。
如果不使用中断去处理溢出这个事件,那么我们就必须通过代码指令让TFx重置为 0 ,并让THx和TLx回归初始值,准备然后进入下一轮周期的计数。
.... if(TF0==1) //如果T0 溢出了 { TF0=0; //重新初始化 TH0 和 TL0 //说明过了一个溢出周期了 }
2个重要的寄存器:TMOD 和 TCON
复位时所有位全 为 0
TFx:溢出标志位。溢出时置1。正常为0。
TRx:计数器/定时器 启动停止控制位 。R是run的意思。 TR0 = 1 开启定时器0,为TR0 = 0 则停止。
低4位与外部中断相关,这里用不到,先不用看。
复位时所有位全 为 0
高4位是定时器T1相关的,低4位是T0 相关的。
以T0来说明。
GATE: 门控制位
C/T : 定时器/计数器切换位。 1为计数器模式, 0 为定时器模式。
②处 C/T = 0 表示为定时器模式,触发信号为①处的单片机内部时钟信号。(若②处CT = 1,则触发信号为Tn脚,信号从P3.4 或者P3.5输入单片机)
③处表明,信号能触发使加法计数器加1,还得受④处控制。不然时钟信号是不能让加法计数器累加的。 ④处这个是与门,TRn必须为1,表明我们要开启定时器。同时GATE为0,通过非门后为1,再通过或门,也是1,那么就让③处控制起来了。
(若GATE为1,那么,定时器的启动停止受 TRx和 INTx 共同控制。 )
于是我们需要:
TRn 为 1
GATE 为 0
INTn 为 X(X表示任意的意思,do not care)
加法存储寄存器的工作模式,是由M0和M1共同来决定的
M1 M0 模式
时钟周期和机器周期
顺便提一下:标准C51的1个机器周期为12个时钟周期(增强型51单片机的机器周期会短一些,cc2530只有的机器周期只等于1个时钟周期)。
如果晶振的频率是11.0592MHz,那么时钟周期就是 1 / (11.0592x10^6) 秒 (1MHz = 10^6Hz)
那么,无论是定时器,还是计数器,每隔1个机器周期 ,加法存储器就1,代表时间经过了 12 x 1 / (11.0592x10^6) 秒。这就是我们衡量的基础依据。
为THx和TLx赋初始值
若TH0 和 TL0 以 16位 模式工作,那它的计数范围为 [0 , 65535 ] , 也就是累加 65536次发生溢出。 每累加一次是 12 / (11.0592x10^6) 秒。
那么从 0 累加到溢出 历时 ≈ 0.071s = 71ms 。
我们一般需要延时 10的整数倍ms,以便用倍数控制更长的延时时间。所以,我么要给 TH0 和 TL0赋一个初始值,使他们的溢出周期(TH0,TL0从初始值到溢出所用的时间)减少到 10ms,或者1ms。
就像一个瓶子,开始装了2/3,再来就只能装1/3就溢出了。
12 / (11.0592x10^6) s ----- 1 次
10x 10-3 s ------ x 次 (求出 x = 9216次 ,计数9216次后溢出)
65536 - 9216 = 56320 = 二进制( 11011100 00000000)
也就是 TH0 = 11011100 , TL0 = 00000000
代码例子验证
#include
8位重装模式
8位重装模式是:只有TL0计数,TH0不变,他只为TL0提供初始值。当TL计数溢出后,TF0就为1,如果继续工作,TH0就把自己的值赋给TL0,再开始计数,如此循环下去。
上面些写了一个毫秒级的delay函数,下面用8位重装模式写一个控制微秒级别的函数。并控制P0.0的LED实现呼吸灯。
计算方法和上面一样,大家可以自己算
#include
值得注意的地方
我们应该尽量让溢出周期 越长越好。溢出周期为10ms 的优于 1ms 的。因为,在同样的延时时间下,如100ms,溢出周期为10ms 的 只需要溢出10次,为TH0 和 TL0重新赋值10次,而溢出周期为1ms的要溢出100次,为TH0 和 TL0重新赋值100次。减少溢出次数和赋值次数,可以减轻单片机的负担,提高定时的准确性。
/***************************************************/
欢迎转载,请注明出处:
为了获得更好的阅读体验,请访问原博客地址。
代码钢琴家
/***************************************************/
作者:代码钢琴家
出处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。为了获得更好的阅读体验,请访问原博客地址。限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
全部0条评论
快来发表一下你的评论吧 !