【51单片机 】定时器的初始值计算 详解

首先值得一提的是:51单片机定时器与主程序是并行工作的,就是主程序在运行的时候,定时器也在计数,计数溢出后定时器中断主程序的运行,转而执行中断服务程序。此外还有串行口、中断系统…,都独立的工作,不用 CPU 干预。

正文部分:

好了,我们先来看初始值计算公式:

公式:(216 X)× 12 ÷ 晶振频率 = 定时时间(默认单位us
—————————————————————————————————
X是未知量
—————————————————————————————————
216是根据方式选择的,可以自行选择,方式1为16位
方式0 :213 (少用)
方式1 :216 (最常用)
方式2 :28 (常用)

假设:

定时器T0工作在方式一,晶振频率为11.0592MHZ,需要定时时间0.5s

那么计算思路是这样的:
1. 首先要知道1s=1000ms,1ms=1000us。
2. 由公式可得:(216-0)× 12 ÷ 11.0592=71ms,定时时间最大只能算到71ms,而0.5s=500ms,距离需要的时间还差429ms,剩下的怎么办?
3. 所以,这个时候我们需要退一步计算,算个5ms再循环个100次,这样就可以得到5ms*100=500ms(0.5s)。

5ms的定时时间先换算成us单位就是5000us
公式:(216-X)× 12 ÷ 11.0592=5000(us)
得 X=60928
把十进制60928转换为16进制=0xee00,分配高8位TH=0xee,低8位TL=0x00,
初始值这样就算好了。

转换进制不熟练的同学可以用win10自带的计算器进行转换。

#include<reg51.h>
   char i=100;    //用来循环100次,5ms*100=500ms,500ms=0.5s
   
  void Timer0Init(void)	 //5毫秒@11.0592MHz 定时器T0 子程序
{
	TMOD &= 0xF0;  //设置定时器模式
	TMOD |= 0x01;  //设置定时器模式
	
	TL0 = 0x00;	   //低8位
	TH0 = 0xEE;	   //高8位
	    //高8位与低8位共同组成初始值
	
	TF0 = 0;	   //清除TF0标志
	TR0 = 1;       //定时器0开始计时
	ET0 = 1;      //允许定时器T0开启中断
	EA = 1;		  //开启总中断
}

  void main()			//主程序
{
        P2=0Xff;         //led初始化  
        Timer0Init();	//调用定时器的初始化子程序
		while(1);      //等待定时器进入中断
}

  void T0_timer0() interrupt 1       //定时器0 进入中断程序
{
		TH0=0xEE;   //这里需要重新赋初始值,保证每次进入中断函数都是5ms
		TL0=0x00;
     	i--;           //i=100开始循环自减
	      if(i<=0)    //判断(i从100减到0的时候就执行下面程序)
		{
			i=100;   //进来就重置循环次数,保证出去可以重新开始计算
		   P2=~P2;    //取反,i从100减到0刚好是0.5s,取反亮一次
		}	     //亮完后i已经等于100,不满足if判断条件,重新开始定时
}
//end 

当然,有更方便的计算方式,在烧录软件找到定时计算器,选好定时器、工作方式、时钟以及定时长度(初始值),就能自动得到初始值了
在这里插入图片描述

上图四个疑问
1、

定时长度:
看上面公式,我们用到定时器方式一是16位,既216,最大只能算出71ms,我们定时单位是ms的话超出71是没有办法计算的,所以这就是为什么不直接输入500ms的原因。
我们可以输入5ms算出初始值然后循环100次再运行
也可以输入50ms得到初始值循环10次再运行,结果都是一样的。

2、

选择定时器:
定时器0和定时器1都可以选择,只是有优先级设置——通过IP寄存器设定,但只有高和低两种,同等优先级时,先响应定时器0。
只使用一个定时器时,随便选一个就行。

3、

定时器模式:
1.模式分8、13、16位(具体看下表 定时器模式表),因为我们选择了方式一(216),所以在模式中选择16位。
2.自动重载与无自动重载区别:无自动重载(下表方式0和方式1)特点是计数溢出后计数器全为0,在使用循环定时/计数时会影响精度。自动重载就是为了解决该问题而设计的。

注意:89c52是没有 16位重载 的,选择的时候具体要看单片机手册,这里选 16位 即可。

4、

定时器时钟:
标准8051单片机为12T。
STC12系列有1T和12T,具体看芯片手册,这里不多赘述。

另外,软件里面的程序也是可以直接使用的,只是要稍微修改一下。
删除不用的(AURX)
加入开启条件:
ET0 = 1; //允许定时器T0中断。选择定时器1时改为ET1=1;
EA = 1; //开启总中断
(具体可看上面的代码)
在这里插入图片描述

用软件里的定时功能计算减去了我们自己写和计算的步骤,方便快捷准确,没用过的可以试一下哦。
定时器模式表:
定时器方式
选择相应的方式:
方式0 :213,(不常用)
方式1 :216 ,(最常用)
方式2 :28,(常用)
方式3 :现在基本上没人用了,稍微了解下即可

补充内容:关于定时器为什么进入中断后需要再次赋初始值?

首先, 8051的定时器只有方式二为自动重载,意思进中断后出去会自动重新开始计数,如果你使用的是方式二,那么就不用重新赋值。(虽然方便,但定时器的每次最大定时时间变短了,计数器到达255us就会溢出)。
其次,如果你采用的是其它方式,如:方式三的16位模式。在开始时,定时器减去初始装载值然后刚好达到需要的时间便溢出(这时候已经从65535跳为0了)进入中断。那么进入中断后TH0和TL0已经不是你在外面赋的初值了,出去会重新从0开始计算,这样会大大影响精度,所以需要在中断里重新赋初始值,保证出去后从上次的地方开始计数,这样就保证了精度。

举个例子:你有一个计数器,从0-100s的,只有归0后才会响。但是你想设置10s就响一次,那么你并不需要等待0~100s这么长的时间,这个时候就需要给它一个初值了,设置从90s开始计数,达到100s后刚刚好为10s,这个时候计数器会响一次,但是响完后它已经是0了,想要重新响需要100s后才能响,所以,最好的办法就是响铃后自动给它重新定一个从90s开始的计数,这样就能实现每10s响一次了。

定时器的原理便是如此。

  • 95
    点赞
  • 479
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值