单片机基础教程【玖】——定时器

-回复 -浏览
楼主 2021-04-05 12:15:40
举报 只看此人 收藏本贴 楼主

好久没更新了..

一开学就好忙~

不过我们的校内电子设计竞赛

就快要开始了。

这几天多更新点。。


中断概述


上节的内容是外部中断

这节我们介绍另一种非常重要的中断——

定时器中断


大家可能都忘了中断源有哪些,放上图


什么是定时器中断呢?


其实就是

过一段时间 (定时周期)

就执行 某一段程序 (中断子程序)


打个比方:

宿舍楼的阿姨/大爷

每隔一个月查一次水表


也就是说,我们可以将需要定期执行的程序

利用定时器功能来实现


首先,定时器具有定时的功能

比如我给定时器设定定时时间为 10ms

那么在这之后过了 10ms

定时器将发出一个中断请求

让单片机运行中断子程序中的内容


定时器主要用在:

  1. 把比较重要的或者需要每隔一定时间执行一次的程序放在定时器内,确保其能定期被运行。

  2. 精确计时,做秒表、时钟等应用。


我们所使用的单片机(STC89C52RC)

是传统MCS-51单片机的升级版

其内部有三个定时器中断源(T0 T1 T2)

其中 T2定时器的某些特性和 T0 T1 不同

我们在这里只讲解 T0 T1 部分


在这之前,我们先了解一下单片机的时钟系统~


单片机时钟系统


我们先了解下面几个概念:


时钟周期:

单片机晶振的震荡周期,频率的倒数。


机器周期:

完成一个基本操作的时间单元叫做机器周期。

一个机器周期由若干个时钟周期构成。

我们所使用的单片机其机器周期由12个时钟周期构成。

即: 机械周期 = 12 × 时钟周期


指令周期:

完成一条指令所需的时间。

简单的指令是单机器周期指令;复杂的为双机器周期指令和多机器周期指令.

由于我们使用C语言编程,编译时会转换成机器语言

由于编译器的不同,相同的语句可能会编译成不同的指令

如赋值语句:  i=0;

有可能是一条单机器周期指令

也有可能是一条双机器周期指令

准确的指令周期需要根据汇编程序来确定哦~


我们可以看到开发板上的晶振

画圈的就是我们单片机的晶振

上面写着 11.0592  单位是兆赫兹(MHz)

那么我们单片机的时钟周期是 (1/11.0592M) s

这个晶振是可拔插的,我们可以使用不同频率的晶振

改变单片机的时钟周期,相应的单片机的运行速度也会改变

(有的板子配的是12MHZ的晶振哦)

如果晶振是12M的话,那么时钟周期就是

1/12000000 秒

对应的机械周期就是

1/12000000 × 12 = 1/1000000 = 1 us

机械周期正好是1us

这会方便我们的计算

所以初学者用12MHz 的晶振比较多哦~

(那么为什么会有11.0592MHz 这种频率的晶振呢?其实是为了串口通信时的便利,这个我们以后会说的~)


下面的内容为了方便理解与计算,就假设我们使用的晶振是12MHz。

那么机械周期就是 1 us

而定时器就是以1个机械周期作为最小计时值的。


接下来我们就看看定时器的SFR(特殊功能寄存器)有哪些?


定时器的主要寄存器



定时器主要寄存器如下:

寄存器TMOD我们先放一放


先看一下 ET0  ET1

是不是跟上节的 EX0  EX1 相对应呢?

没错,这就是定时器的使能控制位

也就是说

ET0 = 0 ; //中断未使能 即使定时时间到了也无法进入中断

ET0 = 1 ; //中断使能,能够正常进入中断。

(由于定时器0和定时器1的部分寄存器使用方法完全相同,只讲解定时器0的部分寄存器,定时器1使用方法可自己推导)


ET0 ET1控制定时器0和1的中断是否使能


另一个寄存器 TR0

即定时器0的运行控制位


TR0 = 0 ; //定时器处于关闭状态

TR0 = 1 ; //定时器开始运行


其实相当于定时器开始计时的开关~


下面我们讲一下比较特殊的TMOD寄存器(定时器工作方式寄存器)


可以看到 TMOD寄存器 由8个位组成(D0-D7)

我们将其分为左右两部分

左边(高位)的对应定时器1 ,右边(低位)对应定时器0

我们先讲右边的定时器0部分:



D3 GATE    置1时只有在INT0脚为高电平及TR0置1时才能打开定时器0

D2 C/T    置0则定时器0用作定时器 置1用作计数器

D1 M1    和M0共同设置定时器工作模式

D0 M0    和M1共同设置定时器工作模式


其中

GATE位较不常用,这里不做讲解,默认置0。

C/T位用于配置计数器/定时器模式,我们这里用其定时器功能,将其置0。当用到计数器功能时 应置1

(计数器就是用外部脉冲进行计数,这里不多讲)

前面这两位寄存器我们这里不适用,全部置0。


后面的 M0 M1位 我们需要重点关注

他俩共同决定了定时器的工作模式,如图:


M0 M1共同决定了定时器工作模式


M0M1均为0时,为工作方式0,即13位定时器

M0为1,M1为0时,为工作方式1,即16位定时器

工作方式2会在串口部分讲解,这里不多说

工作方式3不常用,就不说啦。


至于什么是13位定时器、16位定时器呢?

这就跟前面说的 TH0 TL0 寄存器有关了

这两个寄存器都是8位寄存器

能够存储 0-255 之间的二进制数

在单片机中用来存储当前的计时值


计时/计数规则就是:

定时器运行时,每经过一个机器周期,TL0自加1;


也就是说

TL0初值为0时,经过255个机器周期后(255us)

TL0加到最大值,这时再加就会溢出,这导致单片机可定时的时间极短(几百us)

时间那么短,我们用起来就会很不方便


所以,厂家想到了一个办法

那就是将TH0TL0这两个8位寄存器级联

如下图:

13位定时器模式


TH0的高3位舍弃不要

低5位和TL0的8位组成了一个

13位的存储区域


同样的道理,两个寄存器最多能组成一个16位的定时器:


16位定时器模式


他们工作起来是这样配合的:

TL0累加进位至TH0

就这样,可定时的时间范围变大了,

可以达到2^16=65535us=65.535ms


我们就以16位定时器为例子

(实际应用中16位模式用的比较多~)

当这个16位定时器累加至65535us后

再经过一个机器周期,会导致最后的溢出

产生一个中断请求,进入中断子程序

这样就是一个基本的定时器中断过程


看图更好理解一些~


再此基础上,假设我们每次发产生中断就立即

对TH0和TL0的值进行重装载置0,

那么定时器就会不断的运行,并且每隔一段时间T中断一次



前面我们每次都对TH0 TL0 重装载0值

假设我们装载一个中间值呢?

比如 64535

(二进制: 1111110000010111)

(十六进制: 0xFC17  即TH0=0xFC; TL0=0x17;)




每隔1000us 产生一次定时器中断。

即定时器中断子程序每过 1000us 被执行一次

(以上数据均在12MHz晶振下成立~)


现在我们理一理配置定时器0的思路:


  1. 配置 TMOD 寄存器

  2. TH0 TL0 赋初值

  3. 打开定时器开关 TR0

  4. 打开定时器0中断开关 ET0

  5. 打开总中断开关 EA


然后定时器就跑起来了~

当然还有一个中断子程序不要忘了写

至于怎么写..篇幅有限,下次再讲。。。


So...定时器的基本原理就那么多了~


这些内容说一下只用十几分钟

写成文字要好久。。

还要画图- -||

都写了那么多了,看来定时器要分成两节来写了

下一节继续讲定时器的应用~


PS:定时器真的是单片机的精髓啊,可能也是刚开始入门单片机唯一有点难的地方了,但是学好定时器实在是非常重要的~!定时器的应用太多太多了,巧妙地利用好定时器可以做好多复杂的事情了~

一开始接触有可能觉得看不太明白,因为涉及到寄存器这方面的东西算是比较抽象了,所以学习单片机真的要实践啊,光看看文章是没用的啊,写十几个定时器应用的程序,全部都会搞通的!

我要推荐
转发到

友情链接