【C51】单片机定时器介绍

控制/MCU

1865人已加入

描述

【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   模式  
0   1   TH和TL2个组成16位计数存储器模式  
1   0   TH负责初始化TL,TL计数。8位重装模式  
0   0   THx的8位和TLx的位5组成13位加法计数器(很少用)  
1   1   基本不用  

时钟周期和机器周期

 

顺便提一下:标准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 typedef unsigned int uint; /**************函数声明******************/ void delay10ms(uint m) ; void delay1ms(uint m) ; /********************************/ /*****************************/ sbit LED = P0^0; /*****************************/ void main() { while(1) { LED = 1; delay10ms(100); // delay1ms(1000) LED = 0; delay10ms(100); // delay1ms(1000) } } void delay10ms(uint m) //溢出周期为10ms { /******************** 使用到的寄存器(位) TH0 TL0 TCON: TR0 TF0 TMOD: ***********************/ uint count =0; TMOD = 1; //GATE = 0 C/T =0 M1 = 0 M0 = 1; 16位计数器 TL0 = 0 ; TH0 =220 ; TR0 = 1; for(;count<m;) { if(TF0 == 1) { TF0 = 0; TL0 = 0; TH0 = 220; ++count; } } TR0 = 0; //关闭定时器 } void delay1ms(uint m) //溢出周期为1ms { uint count=0; TMOD = 1; //计时器0以16为存储计时器工作 TH0 = 252 ; TL0 = 102; TR0 = 1; for(;count<m;) { if(TF0==1) //发生一次溢出,也就是过了1ms { TF0=0; //溢出位清零,取消警报 TH0 = 252 ; //重新配置初始值 TL0 = 102; count++; //溢出次数加1 ,溢出1次是1ms,溢出t次就是t ms } } TR0 = 0; }

8位重装模式

8位重装模式是:只有TL0计数,TH0不变,他只为TL0提供初始值。当TL计数溢出后,TF0就为1,如果继续工作,TH0就把自己的值赋给TL0,再开始计数,如此循环下去。

上面些写了一个毫秒级的delay函数,下面用8位重装模式写一个控制微秒级别的函数。并控制P0.0的LED实现呼吸灯。

计算方法和上面一样,大家可以自己算

#include typedef unsigned int uint; # define TRUE 1 # define FALSE 0 /**************函数声明******************/
void
delay1ms(uint t); /********************************/ sbit LED = P0^0; void main() { int step = 0; int again = FALSE; while(1) { LED = again?0:1; delay1ms(step); LED = again?1:0;; delay1ms((500-step)); step+=1; if(step>500) { step =0; again = !again; } } } void delay1ms(uint m) //延时t微秒 { int count=0; TMOD = 2; TH0= 255 ; TL0= 255; TR0=1; for(;count!=m;) { if(TF0==1) { TF0=0; //自动重装 count++; } } TR0=0; }

值得注意的地方

我们应该尽量让溢出周期 越长越好。溢出周期为10ms 的优于 1ms 的。因为,在同样的延时时间下,如100ms,溢出周期为10ms 的 只需要溢出10次,为TH0 和 TL0重新赋值10次,而溢出周期为1ms的要溢出100次,为TH0 和 TL0重新赋值100次。减少溢出次数和赋值次数,可以减轻单片机的负担,提高定时的准确性。

/***************************************************/

欢迎转载,请注明出处:

为了获得更好的阅读体验,请访问原博客地址。

代码钢琴家

/***************************************************/

作者:代码钢琴家 
出处: 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。为了获得更好的阅读体验,请访问原博客地址。限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分