跳转至

定时器与计数器

STC89C52 内置 3 个 16 位定时器/计数器(T0、T1、T2),是单片机编程中最常用的外设之一。

基本概念

  • 定时器模式:对内部机器周期(晶振分频后的时钟)计数,实现精确定时
  • 计数器模式:对 P3.4/T0 或 P3.5/T1 引脚的外部脉冲计数

定时器 0 和定时器 1

相关 SFR

寄存器 地址 功能
TMOD 89H 模式控制(T0 低 4 位,T1 高 4 位)
TCON 88H 运行控制和溢出标志(可位寻址)
TH0 8CH 定时器 0 高 8 位
TL0 8AH 定时器 0 低 8 位
TH1 8DH 定时器 1 高 8 位
TL1 8BH 定时器 1 低 8 位

工作模式

模式 0 — 13 位定时器

  • THx 8 位 + TLx 低 5 位 = 13 位
  • 最大计数值:2^13 = 8192
  • 已基本弃用,了解即可

模式 1 — 16 位定时器(最常用)

  • THx 8 位 + TLx 8 位 = 16 位
  • 最大计数值:2^16 = 65536
  • 定时范围最灵活

模式 2 — 8 位自动重载(常用)

  • TLx 8 位计数,THx 8 位存重载初值
  • 溢出后 TLx 自动从 THx 重载
  • 适合产生精确定时脉冲(如串口波特率)

模式 3(仅定时器 0)

  • 定时器 0 拆分为两个独立的 8 位定时器:TL0 和 TH0
  • 定时器 1 在此模式下停止运行

初值计算

以 12MHz 晶振、12T 模式为例: - 机器周期 = 12 / 12MHz = 1μs - 定时 1ms 需要的计数值 = 1000μs / 1μs = 1000 - 初值 = 65536 - 1000 = 64536 = 0xFC18

// 定时器 0 初始化,模式 1(16 位),定时 1ms
void Timer0_Init() {
    TMOD &= 0xF0;    // 清除 T0 配置位
    TMOD |= 0x01;    // T0: 模式 1(16 位定时器)
    TH0 = 0xFC;      // 高 8 位初值
    TL0 = 0x18;      // 低 8 位初值
    ET0 = 1;         // 使能定时器 0 中断
    EA  = 1;         // 开总中断
    TR0 = 1;         // 启动定时器 0
}

// 定时器 0 中断服务函数
void Timer0_ISR() interrupt 1 {
    TH0 = 0xFC;      // 重载初值(模式 1 需手动重载)
    TL0 = 0x18;
    // 用户代码:每 1ms 执行一次
}

自动重载模式(模式 2)示例

// 定时器 1 模式 2,用于串口波特率发生器
void Timer1_Init() {
    TMOD &= 0x0F;    // 清除 T1 配置位
    TMOD |= 0x20;    // T1: 模式 2(8 位自动重载)
    TH1 = 0xFD;      // 重载值(11.0592MHz 下 9600bps)
    TL1 = 0xFD;      // 当前计数值
    TR1 = 1;         // 启动定时器 1
}

定时器 2

相关 SFR

寄存器 地址 功能
T2CON C8H 控制寄存器(可位寻址)
T2MOD C9H 模式寄存器
TH2 CDH 高 8 位
TL2 CCH 低 8 位
RCAP2H CBH 捕获/重载高字节
RCAP2L CAH 捕获/重载低字节

工作模式

模式 功能
16 位自动重载 与 T0/T1 模式 2 类似,但为 16 位
16 位捕获 检测外部信号跳变时捕获当前计数值
波特率发生器 串口模式 1 和 3 的波特率可选由 T2 产生
可编程时钟输出 从 P1.0 输出可编程频率的方波

自动重载模式初值计算

// 定时器 2,16 位自动重载,定时 50ms(12MHz,12T)
// 计数值 = 50000μs / 1μs = 50000
// 初值 = 65536 - 50000 = 15536 = 0x3CB0
void Timer2_Init() {
    T2CON = 0x00;    // 停止定时器 2
    RCAP2H = 0x3C;   // 高 8 位重载初值
    RCAP2L = 0xB0;   // 低 8 位重载初值
    TH2 = 0x3C;      // 当前计数值高 8 位
    TL2 = 0xB0;      // 当前计数值低 8 位
    ET2 = 1;         // 使能定时器 2 中断
    EA  = 1;         // 开总中断
    TR2 = 1;         // 启动定时器 2(T2CON.2)
}

void Timer2_ISR() interrupt 5 {
    TF2 = 0;         // 清除溢出标志(需软件清零)
    // 用户代码:每 50ms 执行一次
}

1T/12T 速度模式

STC89C52 可通过 AUXR 寄存器的 T0x12/T1x12 位选择定时器速度: - 12T 模式(默认):传统兼容,机器周期 = 12 时钟 - 1T 模式:加速模式,机器周期 = 1 时钟(速度快 12 倍)

// 设置定时器 0 为 1T 模式
AUXR |= 0x80;    // T0x12 = 1

// 设置定时器 1 为 12T 模式(默认)
AUXR &= ~0x40;   // T1x12 = 0

⚠️ 切换 1T 模式时初值需重新计算(计数值 ×12)

定时器用作计数器

只需将 TMOD 中的 C/T 位置 1: - T0 计数输入:P3.4 引脚 - T1 计数输入:P3.5 引脚 - 外部脉冲下降沿触发计数

// T1 作为计数器,对外部脉冲计数
TMOD &= 0x0F;
TMOD |= 0x50;    // T1: 计数器模式,模式 1(16 位)
TH1 = 0x00;
TL1 = 0x00;
TR1 = 1;         // 启动计数

// 读取计数值
unsigned int count = (TH1 << 8) | TL1;