776 字
2 分钟
51单片机定时器原理与应用详解
51单片机定时器原理与应用详解
51单片机内置两个16位定时器/计数器——T0和T1,是嵌入式开发中最基础也最重要的外设之一。无论是LED闪烁、串口波特率生成,还是PWM输出,都离不开定时器。
定时器基础知识
什么是定时器?
定时器本质上是一个加1计数器。每个机器周期(12个时钟周期),计数器自动加1。当计数器从最大值溢出回到0时,触发中断标志。
以12MHz晶振为例:
机器周期 = 12 / 12MHz = 1μs也就是说,计数器每1μs加1。
相关寄存器
| 寄存器 | 地址 | 功能 |
|---|---|---|
| TMOD | 0x89 | 定时器工作模式控制 |
| TCON | 0x88 | 定时器控制与中断标志 |
| TH0/TL0 | 0x8C/0x8A | 定时器0高/低字节 |
| TH1/TL1 | 0x8D/0x8B | 定时器1高/低字节 |
TMOD寄存器详解
TMOD是一个8位寄存器,高4位控制T1,低4位控制T0:
位7: GATE1 - 门控位位6: C/T1 - 定时/计数选择 (0=定时, 1=计数)位5-4: M1M01 - T1模式选择位3: GATE0 - 门控位位2: C/T0 - 定时/计数选择位1-0: M1M00 - T0模式选择四种工作模式
模式0:13位定时器
THx 8位 + TLx 低5位 = 13位计数器最大计数值:2^13 = 8192
这是为了兼容老款8048单片机,实际开发中很少使用。
模式1:16位定时器(最常用)
THx 8位 + TLx 8位 = 16位计数器最大计数值:2^16 = 65536
定时时间计算公式:
定时时间 = (65536 - 初值) × 机器周期例如12MHz晶振下定时50ms:
初值 = 65536 - 50000 = 15536TH0 = 15536 / 256 = 60 = 0x3CTL0 = 15536 % 256 = 176 = 0xB0模式2:8位自动重装
THx存储重装值,TLx为计数器TLx溢出后,THx的值自动装入TLx,无需手动重装。适合精确的周期性定时,如串口波特率生成。
模式3:双8位定时器(仅T0)
将T0拆分为两个独立的8位定时器,此时T1停止工作。
实战代码
示例1:LED每500ms闪烁
#include <reg52.h>
sbit LED = P1^0;
void Timer0_Init() { TMOD |= 0x01; // T0模式1(16位定时器) TH0 = 0x3C; // 50ms初值高字节 TL0 = 0xB0; // 50ms初值低字节 EA = 1; // 开总中断 ET0 = 1; // 开T0中断 TR0 = 1; // 启动T0}
unsigned int count = 0;
void Timer0_ISR() interrupt 1 { TH0 = 0x3C; // 重装初值 TL0 = 0xB0; count++; if (count >= 10) { // 50ms × 10 = 500ms count = 0; LED = ~LED; // 翻转LED }}
void main() { Timer0_Init(); while (1) { // 主循环可做其他事 }}示例2:产生1kHz方波(P1.0)
#include <reg52.h>
sbit WAVE = P1^0;
void Timer0_Init() { TMOD |= 0x02; // T0模式2(8位自动重装) TH0 = 256 - 500; // 12MHz下500μs TL0 = TH0; EA = 1; ET0 = 1; TR0 = 1;}
void Timer0_ISR() interrupt 1 { WAVE = ~WAVE; // 每500μs翻转,周期1ms = 1kHz}
void main() { Timer0_Init(); while (1);}定时器初值速查表
12MHz晶振,模式1下的常用初值:
| 定时时间 | TH0 | TL0 | 计算过程 |
|---|---|---|---|
| 1ms | 0xFC | 0x18 | 65536-1000=64536 |
| 10ms | 0xD8 | 0xF0 | 65536-10000=55536 |
| 20ms | 0xB1 | 0xE0 | 65536-20000=45536 |
| 50ms | 0x3C | 0xB0 | 65536-50000=15536 |
| 100ms | 0x78 | 0x60 | 65536-100000(需多次) |
注意: 16位定时器单次最大定时约65.536ms(12MHz),超过需要软件计数。
常见问题
为什么定时不准?
- 晶振频率不对 — 确认实际晶振频率
- 中断服务程序太长 — ISR执行时间会影响定时精度
- 没有重装初值 — 模式1必须手动重装
如何提高精度?
- 使用11.0592MHz晶振(串口通信友好)
- 在ISR开头立即重装初值
- 避免在中断中执行耗时操作
总结
| 模式 | 位数 | 自动重装 | 适用场景 |
|---|---|---|---|
| 模式0 | 13位 | 否 | 基本不用 |
| 模式1 | 16位 | 否 | 通用定时 |
| 模式2 | 8位 | 是 | 波特率生成 |
| 模式3 | 双8位 | 否 | 特殊需求 |
定时器是51单片机的核心外设,掌握它对后续学习中断、串口、PWM都至关重要。建议从模式1开始练习,理解初值计算后再尝试其他模式。
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
51单片机定时器原理与应用详解
https://mizuki.mysqil.com/posts/51-mcu-timer/ 部分信息可能已经过时





