8051模拟器汇编入门(9)定时器

原始的8051有两个计数器定时器(Timer)。定时器有三个基本功能:

  • 计时和计算事件之间的时间量,这基本上是测量时间;
  • 计数事件,我们将不会在这里关注计数部分,我们将主要关注定时器;
  • 为串行端口生成波特率。

编程定时器

好的,让我们看看如何编程8051定时器。在我们查看编程部分之前,让我们先看看涉及编程定时器的寄存器。

定时器模式 (TMOD) 寄存器: 用于设置定时器的操作模式

定时器寄存器

  •   定时器0和定时器1 – 16位宽
  •   用于加载定时器计数值

定时器控制 (TCON) 寄存器: 用于启动或停止定时器

现在,这些是你编程8051定时器需要采取的步骤:

  1. 设置定时器模式;
  2. 设置定时器寄存器;
  3. 运行定时器,
  4. 监控定时器标志位。

定时器模式寄存器(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,让我们参考这个表格。

M1M0模式操作
0013位定时器模式13位定时器/计数器,THx的8位和TLx的5位
0116位定时器模式16位定时器/计数器,THx与TLx级联
108位自动重载模式8位定时器/计数器(自动重载模式),TLx在THx溢出时用THx的值重载
11分割定时器模式将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