嵌入式——定时器中断

先上代码算法

#include <reg52.h>

void Init();

void main(){
    Init();
}

void Init(){
    TMOD = 0x01;
    TH0 = 0x4b;
    TL0 = 0xfc;    //定时器时间50ms,针对11.0592MHz频率CPU
    ET0 = 1;
    EA = 1;
    TR0 = 1;
}

void Timer0() interrupt 1 {
    TH0 = 0x4b;
    TL0 = 0xfd;
    //Timer循环体,运行过程放这里
}

示例代码就要有示例代码的样子,简简单单的才能把问题说清楚!函数

先解释下几个变量,TMOD,TH0,TL0,ET0,EA,TR0,这些变量不是我定义的,而是<reg52.h>头文件中的,先掌握用法,再深究原理。学习

 

TMOD:选择定时器的模式,不一样的模式主要是能数到的最大数不一样,通常就用模式1,最大可数到65535spa

TH0:TL0:设置起始值,TH0 故名思议就是数字转为16进制的高8位,TL0为低八位code

TR0:启动、中止定时器,1启动,0中止,这个比较好理解吧blog

EA:容许系统进行中断,1容许,0禁止,算是个权限之类的东西it

ET0:容许定时器0进行中断,1容许,0禁止入门

 

到这里你确定还会有疑问,我接着给你解释!class

 

1.定时器定时时间怎么算的啊,0x4bfc转为10进制并非50啊?变量

 

——确实不是50,在讲定时器时间的算法以前,先得说下这个定时器的原理。

在咱们高级语言习惯中,定时器就是给他设定一个数,他一秒数一下,数到那个值后进行一次定时操做。可是在嵌入式中并非这样,也是由于这样错误的想法,我不理解了好久。

  在嵌入式中,定时器的实现原理是,他从某个数开始数,一直数到上限(如65535),到65536的时候定时器溢出,进行一次操做,而咱们给的0x4bfc是定时器的起始值,也就是说定时器将从这个值开始数,一直数到65535,中间所耗费的时间就是50ms。

 

2.彷佛明白了,那这个时间具体怎么算啊?

 

——恩,这个问题稍有些复杂,回答这个问题以前,仍是要继续引入几个概念。

  时钟周期T1:晶振振荡周期,公式  T1 = 1/频率  ,如11.0592MHz的晶振频率  T1 = 1/11.0592 us

  机器周期T2:机器执行一条基本指令的时间,公式  T2 = 12 * T1  ,如11.0592MHz的机器周期约为  1.085 us

  

  因此,要定时50ms的计算过程

  50ms = 50000us = 50000/1.085 机器周期 = 46083 次

  也就是说,要让计时器数 46083 次就行了,要数到65535,那么很天然就知道是要从 65535 - 46083 = 19452 数起

  19452D = 0x4bfc

  因此 TH0 = 0x4b,  TL0 = 0xfc

 

3.我有注意到,TH0 TL0 TR0 ET0 后面都有0,感受挺奇怪的?

 

——你看的很仔细,没错,这个0是有意义的。事实上,单片机里有两个定时器,TH0表示第一个定时器,TH1表示第二个,另外几个以T开头的都表示定时器变量,也都有T_0和 T_1两种,E开头的表示与中断相关。

 

4.interrupt 1 里面的1是什么意思,能换成其余数字吗?

——后面的1是中断号,Timer0 这个函数名称你能够随便取,可是后面这个数字倒是固定的,由于它是用来讲明这个函数是谁的中断函数,1表示是定时器1来中断,3表示定时器2中断。事实上,还有几个额外的中断类型,可是做为入门,就不在这里列举了。

 

5.为何在中断函数 Timer0 里又从新设置了一次 TH0 和 TL0 呢,这是必须的吗?

 

——上面有提到过,这个函数里面的过程是在定时器数到65536溢出后执行的,可是有个问题是溢出完后TH0 和 TL0就会被重置为0,若是你不从新设定的话它会从0开始数起,因此是必须的,定时器1和定时器2都是这样的。

 

定时器简单的理解到这就差很少了,关于中断还须要继续学习,另外几种中断方式原理上都是有共通点的!

相关文章
相关标签/搜索