1. 51单片机定时器/计数器基础概念
第一次接触51单片机定时器时,我盯着手册上的"增计数器"四个字发懵——这玩意儿不就是个会自己数数的电子秒表吗?后来在项目里被定时不准坑了几次才明白,它远比想象中复杂得多。定时器和计数器本质上都是对脉冲进行计数,区别就像用沙漏计时和数路过汽车:前者用固定频率的机器周期(晶体振荡器12分频后的脉冲),后者则捕捉外部引脚(P3.4/P3.5)的跳变信号。
硬件结构就像两个连体婴儿:T0由TH0、TL0两个8位寄存器组成,T1对应TH1、TL1。它们共用两个控制寄存器——好比大脑的左右半球:
- TMOD(89H):决定工作模式(定时/计数)和方式(0-3)
- TCON(88H):负责启停控制和状态标志
实测发现个有趣现象:即使设置为定时器模式,只要把外部脉冲接入P3.4引脚,修改C/T位就能瞬间变成计数器。这让我想起家里的水电表——计量自来水和用电量本质都是计数,只是信号来源不同。
2. 控制寄存器深度剖析
2.1 TMOD寄存器:模式开关
这个不可位寻址的寄存器就像双控开关,高4位管T1,低4位管T0。每个定时器又分到3个功能键:
- C/T:0=定时器(内部时钟),1=计数器(外部引脚)
- M1/M0:工作方式选择(00-11对应方式0-3)
- GATE:门控位。这个位坑过我——当设为1时,定时器启动需要同时满足TRx=1且INTx引脚为高电平,适合做脉冲宽度测量
// 设置T0为方式1定时器,T1为方式2计数器 TMOD = 0x21; // 0010 00012.2 TCON寄存器:控制中枢
可位寻址的TCON藏着几个关键位:
- TR0/TR1:运行控制位。软件置1后,计数器才开始累加
- TF0/TF1:溢出标志位。查询方式时要手动清零,中断方式则由硬件自动清零
曾经调试时发现定时不准,最后发现是忘了清除TF标志位。这就像煮泡面时没按停闹钟,时间到了还一直响。
3. 四种工作方式详解
3.1 方式0:13位定时器
等效电路像个拼图:TLx的低5位(实际只用5位)和THx的8位拼成13位计数器。最大计数值8192,初值计算公式:
THx = (8192 - X) / 32 TLx = (8192 - X) % 32实测发现个坑:手册上说TLx用5位,但实际操作时还是要给TLx赋8位值,只是高3位无效。这就像买了13寸笔记本,包装箱却还是按15寸设计的。
3.2 方式1:16位定时器
最常用的模式,THx和TLx全用上,构成65536的计数范围。定时公式:
T = (65536 - X) × 机器周期做过一个呼吸灯项目,用方式1实现1ms定时:
TH0 = (65536 - 1000) / 256; // 12MHz晶振 TL0 = (65536 - 1000) % 256;3.3 方式2:自动重装8位定时器
TLx作计数器,THx存重装值。溢出时THx的值自动灌入TLx,就像无限续杯的咖啡。特别适合做串口波特率发生器:
TMOD |= 0x20; // T1方式2 TH1 = 0xFD; // 9600bps@11.0592MHz TL1 = 0xFD;3.4 方式3:双8位定时器
T0的专属模式,把T0拆成两个独立8位定时器:
- TL0占用原T0资源
- TH0借用T1的TR1和TF1
此时T1只能用于不需要中断的场景(如串口波特率)。有次我把T1设成方式3还开了中断,系统直接卡死——就像抢了别人的电话线还奇怪为什么打不通。
4. 定时器应用实战技巧
4.1 初值计算黑科技
12MHz晶振下,机器周期1μs。要定时50ms:
X = 65536 - 50000 = 15536换算成十六进制:
TH0 = 0x3C; TL0 = 0xB0;4.2 长定时解决方案
软件计数器是王道。比如用全局变量做分频:
unsigned char count = 0; void Timer0_ISR() interrupt 1 { TH0 = 0x3C; // 重装50ms初值 TL0 = 0xB0; if(++count >= 20) { // 1秒到 count = 0; P1_0 = ~P1_0; // 翻转LED } }4.3 输入信号要求
计数器模式下,外部脉冲最高频率不能超过晶振频率的1/24。比如12MHz晶振时,最高500kHz。实测发现信号抖动会导致误计数,建议加上施密特触发器整形。
5. 常见问题排查指南
- 定时不准:检查是否忘记重装初值(方式0/1),或中断服务程序执行时间过长
- 计数器不工作:确认GATE位设置,测量外部引脚信号
- 中断不触发:检查ETx和EA是否使能,TF标志是否被意外清除
- 方式3异常:确保T1没有启用中断
有次用示波器抓波形,发现定时误差达到10%。最后发现是没考虑中断响应延迟,在中断开始加上#pragma optimize=none才解决。