原始的8051有两个计数器定时器(Timer)。定时器有三个基本功能:
- 计时和计算事件之间的时间量,这基本上是测量时间;
- 计数事件,我们将不会在这里关注计数部分,我们将主要关注定时器;
- 为串行端口生成波特率。
编程定时器
好的,让我们看看如何编程8051定时器。在我们查看编程部分之前,让我们先看看涉及编程定时器的寄存器。
定时器模式 (TMOD) 寄存器: 用于设置定时器的操作模式
定时器寄存器
- 定时器0和定时器1 – 16位宽
- 用于加载定时器计数值
定时器控制 (TCON) 寄存器: 用于启动或停止定时器
现在,这些是你编程8051定时器需要采取的步骤:
- 设置定时器模式;
- 设置定时器寄存器;
- 运行定时器,
- 监控定时器标志位。
定时器模式寄存器(TMOD)
定时器模式寄存器或TMOD寄存器是一个8位宽的寄存器。低4位用于定时器0,高4位用于定时器1。TMOD寄存器的功能是设置定时器0和定时器1的操作模式。

正如刚才提到的,低4位用于定时器0,高4位用于定时器1。正如你可能已经观察到的,定时器0中的位数与定时器1中的位数是相同的。所以让我们关注定时器零。
如果GATE设置为逻辑1,那么定时器计数器被启用,定时器由中断INT0或INT1控制。如果GATE设置为逻辑0,那么它用于内部时钟。对于第二位C/T0,如果你想将其用作计数器,那么你需要将这个设置为1。如果你想将其用作定时器,这是我们的意图,所以我们需要将这个设置为0。
GATE:
1 = 启用定时器/计数器 - 定时器由 INT0/INT1 控制。
0 = 启用定时器/计数器 - 用于内部时钟。
C/T* (Counter/Timer):
1 = 用作计数器
0 = 用作定时器
我们还需要设置操作模式,所以这里的这两个位M0和M1,让我们参考这个表格。
M1 | M0 | 模式 | 操作 |
0 | 0 | 13位定时器模式 | 13位定时器/计数器,THx的8位和TLx的5位 |
0 | 1 | 16位定时器模式 | 16位定时器/计数器,THx与TLx级联 |
1 | 0 | 8位自动重载模式 | 8位定时器/计数器(自动重载模式),TLx在THx溢出时用THx的值重载 |
1 | 1 | 分割定时器模式 | 将16位定时器分成两个8位定时器,即THx和TLx像两个8位定时器一样 |
现在,为了这个例子编程TMOD,我将复制01H到TMOD。这在二进制中将是0001,因为我不使用定时器1,所以所有位都设置为零。GATE设置为零,因为我使用的是内部时钟。这个用作定时器,所以C/T0设置为零。现在我想在模式1下操作,所以M1设置为0,M0设置为1,这将把定时器0设置为模式1。

定时器寄存器(Timer Register)
首先,让我们看看定时器0寄存器。记住,原始的8051有两个定时器,定时器0和定时器1。所以让我们先看看定时器0寄存器。它是一个16位宽的寄存器,实际上是由两个8位宽的寄存器组成的,如你所见。这是定时器0低字节,这是8位,定时器0高字节,这是8位,我们将其标记为TH0用于定时器高,TL0作为定时器低。所以零表示它们是定时器零。

好的,让我们继续定时器一。正如你所见,它实际上与定时器零寄存器相同。它是一个16位宽的寄存器,由两个8位宽的寄存器组成。定时器1低字节TL1和定时器1高字节TH1。

下面是如何编程定时器寄存器—将某个值复制到这个寄存器中。在这个例子中,我们将3CH复制到定时器零高字节,
MOV TH0, #03CH。
这将把这个值3CH复制到这个寄存器中。然后将这个值B0H复制到定时器零低字节。
MOV TL0, #0B0H。
在二进制中,它将是0011110010110000

这是十六进制的值,所以它是3C这个和B0。对吧,但是是如何得到这个值3CB0的呢?好吧,让我们看看计算要加载到定时器中的值。原始的8051,我将假设我将操作我的控制器在12兆赫兹,所以它是1除以12兆或1200万,这将给我们一微秒。这意味着定时器每增加一微秒就会增加。现在,如果我想计算50毫秒延迟的十六进制值,所以是50毫秒除以一微秒,这将给我五万次增量。我们从65536减去这个五万,65536是16位宽寄存器的最大增量(2^16)。所以65536减去五万将得到15536,所以这些都是十进制数字,所以我们需要将15536十进制转换为十六进制值,这将得到3CB0H。
计算要加载到定时器中的值
- XTAL = 12 MHz
- 12x1/12 000 000 = 1μs
- 定时器每1μs递增
- 示例
- 对于50ms:
- 50ms/1μs = 50000 增量
- 65536 - 50000 = 15536
- 15536 转换为十六进制是 3CB0H
定时器控制寄存器(TCON)
好的,现在让我们来看看定时器控制寄存器或TCON寄存器。定时器控制或TCON寄存器是一个8位宽的寄存器,TCON用于启动或停止定时器。它们还包含指示定时器是否溢出的位。

好的,这里有一些TCON寄存器的更多细节,我将首先关注TF1 TF0,这是定时器溢出标志。所以TF1是定时器1的,TF0是定时器0的。所以当定时器溢出时,溢出标志TF将被设置为1,这意味着从逻辑1过渡到逻辑0时,TF标志将被设置为1。我们将在稍后的演示中看到这一点。

其他相关位是TR定时器运行控制位。TR1是定时器1的,TR0是定时器0的。当TR位设置为1时,它将启动定时器,如果TR设置为0,它将停止定时器。所以基本上TR位将启动或停止定时器。

IE是外部中断边沿标志,IE1和IE0,基本上这是8051用来跟踪边沿触发中断的。

最后我们有外部中断类型控制,所以IT1是定时器1的,IT0是定时器0的。基本上这是由软件设置或清除的,以指定下降沿或低电平触发外部中断。我们在篇文章中不会处理这些中断。

练习
1、使用计时器使P1.2LED以50ms间隔闪烁。
Org 0000H
Here: Mov TMOD,#01H ;Timer 0, mode 1
Mov TH0,#03CH ;TH0 = 3CH, low byte
Mov TL0,#0B0H ;TL0 = B0H, high byte
SetB P1.2 ;Set port 1 bit 2
Acall Delay ;Call delay subroutine
Clr P1.2 ;Clear port 1 bit 2
Acall Delay ;Call delay subroutine
Sjmp Here ;Jump back to Here label
Delay: SetB TR0 ;Start Timer 0
Again: Jnb TF0,Again ;Monitor Timer 0 overflow flag
Clr TR0 ;Stop Timer 0
Clr TF0 ;Clear Timer 0 overflow flag
Ret
End
2、使用计时器完成一个一秒的延迟。
Org 0000H
Main:
SetB P1.2 ; Set P1.2 to 1
ACall OneSec ; Call one sec delay
Clr P1.2 ; Set P1.2 to 0
Acall OneSec ; Call one sec delay
Jmp Main ; Repeat
OneSec:
Mov R3, #14H ; Set counter to 14H (20 in decimal)
Start:
Acall FiftyMSec ; Call 50 mSec delay
Djnz R3, Start ; Check counter
Ret
FiftyMSec:
Mov TMOD, #01H ; Timer 0, mode 1
Here:
Mov TH0, #03CH ; TH0 = 3CH, high byte
Mov TL0, #0B0H ; TL0 = B0H, low byte
Setb TR0 ; Start Timer 0
Again:
Jnb TF0, Again ; Monitor Timer 0 flag
Clr TF0 ; Clear Timer 0 flag
Clr TR0 ; Stop Timer 0
Ret
End