本篇文章整理一下关于定时器如何定时指定的时间,也来详细的整理一下关于定时器/计数器相关的寄存器。本文比较长,中间的过程可能觉得乏味,如果希望直接知道如何简便搞定,直接拉到末尾看 STC-ISP 是如何生成初始化定时器寄存器即可。说实话,这么长的内容不用也会忘记,所以用的时候知道去哪查就行了!
前面的文章把晶振、时钟周期、机器周期这些概念都介绍了,也整理关于晶震频率和时钟周期、机器周期之间的计算,以及机器周期和计数是怎么换算的。
理论知识比较抽象,当理论知识有了以后,接下来就要了解一些比较具象的部分了。那么就把关于定时器相关的寄存器来进行介绍。
关于定时器/计数器的寄存器在手册的 P185 有介绍,如下图所示。
在图中,TL0、TL1、HT0 和 TH1 是用来进行计数的寄存器。其中 TL0 和 TH1 是定时器 0 的低 8 位和高 8 位,TL1 和 TH1 是定时器 1 的低 8 位和高 8 位。
TCON 是定时器的控制寄存器,TMOD 是定时器的工作方式寄存器。它们的说明在手册的 P60,如下图。
TL0 和 TH0 组成了定时器 0,TL1 和 TH1 组成了定时器 1。我们这里就针对定时器 0 展开说明,毕竟它们两个定时器的寄存器概念是相同的。
TL0 是一个 8 位的寄存器,8 位的寄存器可以表示 256 种状态,也就是说,如果单独使用 TL0 可以数 256 下。如果只数 256 下的话,对于我们开发板上的晶振的频率而言,相当于只能是 256 * 1.085 微秒,即约等于 277 微秒的时长。太短了!
TH0 也是一个 8 位的寄存器,如果使用 TL0 和 TH0 构成的 16 位寄存器来计数,那么就相当于可以数 65536 下,那么相当于 65536 * 1.085 微秒,约等于 71 毫秒的时长。也不长,不过比只用 TL0 好很多!
对于这种两个 8 位寄存器构成一个 16 位寄存器的情况其实我们并不陌生,比如在 80x86 架构下,通用寄存器也是有类似情况的,比如 AX 的 AH 和 AL、还有 BX 的 BH 和 BL 等。懂的都懂,不懂的话,考虑一下,如果一个算盘有 8 位,那么两个算盘合在一起,是不是可以算的位数就更多了。
TL0 和 TH0 同时使用可以数 65536 下,大约是 71 毫秒。但是当数到 65536 下的时候会如何呢?
在手册 P186 给出了关于 TCON 的说明,如下图:
从上图可以看出,也就是当数数超过 65536 时会产生溢出,如果使用的是 T0 定时器/计数器的话,那么会影响 TCON 寄存器的 B5 位,也就是 TF0 位。这个和 80x86 架构的 EFLAGS 寄存器的 CF 位类似。
在定时或计数的时候,我们怎么知道定时器的定时可以触发了,或者怎么知道计数的数已经累计完成了?那么就是需要让计数器溢出,也就是让 TF0 或 TF1 的标志位置位。
那我们知道,使用 TL0 和 TH0 可以数 65536 下,数完 65536 下以后经过了 71 毫秒,数到 71 毫秒时 TF0 会被置位。但是,如果我们向要数 10 毫秒的话,如何让 TF0 置位呢?其实我们可以给 TL0 和 TH0 指定一个初始值,不要让 TL0 和 TH0 都从 0 开始数就可以了。
我们可以这样来计算,10毫秒 / 1.085微秒 = 9216,相当于 10 毫秒需要定时器/计数器去数 9216 下。那么数 9216 下以后我们希望 TF0 被置位,那么我们需要从多少开始数呢?即 65536 - 9216 = 56320,也就是我们让 TL0 和 TH0 从 56320 开始数就行了,也就是我们给 TL0 和 TH0 的初始值时 56320 就可以了。让它们从 56320 开始数,数 9216 下,就到了 65536 了,这时 TF0 被置位,此时也就经过了 10 毫秒。
把 56320 转换为 16 进制是 0xDC00,那么设置 TL0 是 0x00,设置 TH0 是 0xDC,这样就可以让它们从 56320 开始数了。
我们请出 STC-ISP 这个软件,这个软件在我们设置软件延时和烧写 HEX 文件时使用过它,其它时候好久没有使用它了。因为最近一直整理的都是概念性的内容了。此时,我们让它帮我们给出一段初始化 TL0 和 TH0 寄存器的代码,如下图所示。
在图中可以看出,TL0 指定的初始值时 0x00,TH0 指定的初始值是 0xDC,和我们手动计算的是一致的。
到此本篇内容就梳理完成了,不知道我表达的是否清楚,因为这部分涉及的寄存器比较多,当然定时器/计数器还有其他的寄存器需要介绍,那么后面的事情。但是就 TL0、TH0 和 TF0 三个寄存器的介绍而言,不知道能否表达的让大家理解。我已经尽力了!