公司动态
AT89C51定时器实战:从方波到PWM脉冲的三种经典信号生成方案
1. AT89C51定时器基础与信号生成原理第一次接触AT89C51定时器时我被它既能定时又能计数的双重特性惊艳到了。这就像你家里有个多功能料理机既能榨果汁又能绞肉馅。定时器本质上是个16位的加法计数器当它接收单片机内部的时钟脉冲时就是定时器模式而接收外部引脚P3.4/P3.5的脉冲时就变身计数器。我实测过在12MHz晶振下每个机器周期正好1微秒。这意味着定时器每计一个数就是1μs这种精确度对生成周期性信号特别有用。记得初学时常搞混TMOD和TCON这两个寄存器后来发现TMOD像定时器的身份证决定工作模式而TCON则是开关面板控制启动停止。定时器有四种工作模式但生成信号最常用的是模式116位定时。比如要产生2ms方波相当于需要定时1ms后翻转电平。通过公式计算初值65536 - 1000因为1ms1000μs这个数值会被拆成高8位和低8位分别存入TH1和TL1。2. 周期2ms方波的两种实现方案2.1 查询法实现查询法就像不断看手表等下课的学生。下面这段代码我调试了三次才成功#include reg51.h sbit P1_0 P1^0; // 定义输出引脚 void main() { TMOD 0x10; // 设置T1为模式1 TR1 1; // 启动定时器 while(1) { TH1 (65536-1000)/256; TL1 (65536-1000)%256; // 装载1ms初值 while(!TF1); // 死等溢出标志 TF1 0; // 必须手动清零 P1_0 !P1_0; // 电平翻转 } }实测中发现两个坑点一是忘记清零TF1会导致只翻转一次二是初值计算错误会产生非对称波形。用示波器测量时建议先检查周期是否准确再观察占空比是否50%。2.2 中断法实现中断法就像设置闹钟到点才处理#include reg51.h sbit P1_0 P1^0; void timer1_isr() interrupt 3 { P1_0 !P1_0; TH1 (65536-1000)/256; // 重装初值 TL1 (65536-1000)%256; } void main() { TMOD 0x10; TH1 (65536-1000)/256; TL1 (65536-1000)%256; EA 1; // 总中断允许 ET1 1; // T1中断允许 TR1 1; while(1); // 主循环空转 }中断法的优势是CPU不用一直查询可以执行其他任务。但要注意中断服务程序要尽量精简我有次在中断里做复杂计算导致信号抖动。两种方法对比如下特性查询法中断法CPU占用率100%1%代码复杂度简单需处理中断定时精度较高受中断延迟影响适用场景单一定时任务多任务系统3. 长周期2s方波的实现技巧当需要2秒的长周期时直接定时会超出16位计数范围最大65.536ms。我的解决方案是化整为零用20ms作为基础定时单元累计100次就是2秒。3.1 中断法实现方案#include reg51.h sbit P1_0 P1^0; unsigned char count 0; void timer1_isr() interrupt 3 { TH1 (65536-20000)/256; // 20ms初值 TL1 (65536-20000)%256; if(count 100) { // 计满100次 count 0; P1_0 !P1_0; // 翻转电平 } } void main() { TMOD 0x10; TH1 (65536-20000)/256; TL1 (65536-20000)%256; EA ET1 1; TR1 1; while(1); }这里count变量要用unsigned char类型如果定时更长时间建议改用int。我曾遇到count溢出导致信号异常的问题后来加了volatile修饰符解决。4. PWM脉冲生成实战PWM脉冲宽度调制就像用开关水龙头控制水流大小。要产生周期20ms、占空比20%的矩形波意味着高电平4ms低电平16ms。4.1 精确占空比控制#include reg51.h sbit P1_0 P1^0; unsigned char pwm_count 0; void timer1_isr() interrupt 3 { TH1 (65536-4000)/256; // 4ms基础单元 TL1 (65536-4000)%256; switch(pwm_count) { case 1: P1_0 0; break; // 第1次中断变低电平 case 5: // 第5次中断 P1_0 1; pwm_count 0; break; } } void main() { TMOD 0x10; TH1 (65536-4000)/256; TL1 (65536-4000)%256; EA ET1 1; TR1 1; P1_0 1; // 初始高电平 while(1); }调试PWM时建议先用LED观察亮度变化再用示波器测量具体参数。占空比调整只需修改case判断条件比如30%占空比就是3:7的比例。5. 工程实践中的经验分享在实际项目中我总结出几个关键点晶振稳定性决定定时精度普通项目用12MHz足够高精度场合建议换11.0592MHz中断服务程序中避免浮点运算我有次因计算耗时导致波形畸变多定时器协同工作时要注意优先级设置TF标志位可能被意外清除使用示波器调试时建议先看整体波形再放大观察边沿细节对于更复杂的信号生成可以结合多个定时器。比如用T0做时间基准T1控制占空比。当需要可变占空比时可以引入外部按键输入来调整计数值。