在51单片机编程中,产生PWM波形是电子设计中常见的需求,尤其在电机控制、信号生成等领域。然而,89C51芯片本身并不具备硬件PWM功能,因此需要通过软件编程的方式来模拟实现PWM波形的生成。本文将详细介绍两种主要的方法:软件延时法和定时器法。
软件延时法是一种简单易懂的方法,它利用软件编程来控制电平的持续时间,从而模拟PWM波形。该方法编写简单,但存在明显的缺点,当单片机需要执行除PWM波形生成之外的其他任务(如键盘扫描、显示操作等)时,CPU的机器周期会被占用,这将影响PWM的准确性和稳定性。由于CPU资源的限制,该方法并不适用于资源需求高的应用场景。
具体实现软件延时法的程序如下:
```c
#include <reg52.h>
sbit pwm = P1^0;
main() {
while(1) {
pwm = 1; // 输出高电平
delayus(40); // 延时40微秒
pwm = 0; // 输出低电平
delayus(60); // 延时60微秒,占空比为60%
}
}
void delayus(uint x) {
while(x--);
}
```
在上述代码中,pwm变量控制P1端口的第0位,通过交替改变该位的电平状态和延时时间来模拟PWM波形。
定时器法是更加常用的方法,它利用定时器中断来改变电平状态,从而产生PWM波形。定时器中断服务程序中通常仅改变标志位或电平状态,因为过多的操作会干扰PWM波形的准确性。在设计中断服务程序时,应避免在中断内部进行复杂的运算,比如除法、取余以及浮点运算,因为这些运算会消耗大量的CPU周期。定时器的初值设置也需特别注意,初值不应设置得过小,以免定时器频繁溢出中断,导致系统紊乱。通常会预留50-100个数的裕量。在选择定时器工作方式时,工作方式1提供16位定时器,适用于需要较宽调频范围的情况。
定时器初值的计算对于产生准确的PWM波形至关重要。举例来说,若要产生频率为f、占空比为α的PWM波形,可以按照以下公式计算定时器高低8位初值:
```c
TH0 = (65535 - a * 100 / fr) / 256; // 定时器高位初值
TL0 = (65535 - a * 100 / fr) % 256; // 定时器低位初值
```
其中,a代表100倍的占空比,fr代表频率的0.01倍值。当需要产生低电平时,公式中的α应替换为(1-α)。
例程部分代码则展示了一个应用定时器T0产生PWM波形的完整程序。在这个程序中,可以通过独立键盘控制PWM的频率和占空比,频率的可调范围为100Hz至10kHz,占空比为0%至100%。为提高中断服务效率,程序中定义了临时变量(T0_H, T0_L, T1_H, T1_L)用于存储定时器初值,并在中断服务程序中直接赋值给寄存器TH0、TL0,避免在中断中进行计算。
在实际的软件仿真中,可以看到不同频率和占空比下的PWM波形表现。例如,在100Hz时,占空比约15%和95%的PWM波形;在10kHz时,占空比15%和90%的PWM波形。这些波形通常在仿真软件中查看,如Proteus等,能够直观地评估PWM的输出质量。
总结来说,在51单片机上实现PWM波形的关键在于合理使用定时器和精确计算定时器初值,同时在中断服务程序中要尽量减少复杂运算。通过定时器法,即便在单片机执行多项任务时,也能保证PWM波形的准确性和稳定性。