本人不揣冒昧,两天前写了个“51单片机软模PWM误差率之研究--基于Keil、Proteus仿真调试”,事后三思,犹不尽之处夥颐;这次趁机添柴,又烧了把火,陈述如下:
在PWM调速中,占空比α是一个非常重要的参数(故,在“之研究”中,本人针对α开刀,进行了详细的误差分析),一般改变α的方法有三:
1、定宽调频法:这种方法保持PWM_HIGH不变,只改变PWM_LOW,这样使周期或频率而随之改变;
2、调宽调频法:这种方法是保持PWM_LOW不变,而改变PWM_HIGH,这样使周期或频率也随之改变;
3、定频调宽法:这种方式是保持周期或频率不变,而同时改变PWM_HIGH、PWM_LOW值,从而达到改变占空比α的目的。
头两种方法由于调速时也改变了控制脉冲的周期或频率,当控制脉冲的频率与系统固有频率接近时,将导致振荡,因此用的较少。故工程控制中,尤其是直流电机的控制中,最主要使用的还是定频调宽法。
本文的定位为:怎样在C51中实现定频调宽(改变α)的同时也保证较低的PWM波形误差率 ?单片机中使用软件模拟的方法输出PWM波其波形频率是否和预期的完全吻合 ?若不吻合,其误差率是多大 ?
上文中,本人特定义了三个重要的参数宏:
#define PWM_CYCLE XXXX //PWM波的一个周期,单位:us;
#define PWM_HIGH XXX //高电平持续时间,单位:us;
#define PWM_LOW XXX //低电平持续时间,单位:us;
接着,不断改变PWM_CYCLE的取值(实际上也是改变PWM的波形频率),在实验和仿真分析的基础上,最后得出这样的结论:在51单片机上采用软件模拟的方式输出PWM波,其频率越大,占空比误差越不可收拾;在PWM波形频率不是很高的情况下(比如小于1kHz),采用软模方式输出PWM是完全可行的;其占空比计算式可写为:(PWM_HIGH+12)/(PWM_HIGH+PWM_LOW+24)。
将PWM波形参数参数写成宏定义的方式有利于程序的编译暨研究的方便性;但这样一来,程序调试正确刷入MCU后运行,则PWM波的频率一定,占空比也一定,达不到调速或调控的目的;为此,本人修改源程序中PWM子模块(PWM.C),追加四个8位的模块级变量:
int8u data gPWM_HIGH_L; //PWM_HIGH的低八位;
int8u data gPWM_HIGH_H; //PWM_HIGH的高八位;
int8u data gPWM_LOW_L; //PWM_LOW的低八位;
int8u data gPWM_LOW_H; //PWM_LOW的高八位;
而保留PWM_CYCLE 宏定义不变,最终确定的中断服务函数为:
extern void Timer1_ISR(void) interrupt 3
{
if(PWM_PIN){PWM_PIN = 0;
TH1 = gPWM_LOW_H;
TL1 = gPWM_LOW_L;}
else {PWM_PIN = 1;
TH1 = gPWM_HIGH_H;
TL1 = gPWM_HIGH_L;}
}
(注:尽量避免在中断服务函数中执行16位计算,这样只会使PWM波形误差雪上加霜 !)
在Keil中编译后的汇编代码(默认8级优化)如下:
; FUNCTION Timer1_ISR (BEGIN)
; SOURCE LINE # 63
; SOURCE LINE # 65
0000 309709 JNB PWM_PIN,?C0002
; SOURCE LINE # 66
; SOURCE LINE # 67
0003 C297 CLR PWM_PIN
; SOURCE LINE # 68
0005 85008D R MOV TH1,gPWM_LOW_H
; SOURCE LINE # 69
0008 85008B R MOV TL1,gPWM_LOW_L
; SOURCE LINE # 70
000B 32 RETI
000C ?C0002:
; SOURCE LINE # 72
; SOURCE LINE # 73
000C D297 SETB PWM_PIN
; SOURCE LINE # 74
000E 85008D R MOV TH1,gPWM_HIGH_H
; SOURCE LINE # 75
0011 85008B R MOV TL1,gPWM_HIGH_L
; SOURCE LINE # 76
; SOURCE LINE # 77
0014 ?C0004:
0014 32 RETI
; FUNCTION Timer1_ISR (END)
这代码与先前的几乎相同,只不过将立即数寻址改变成了直接地址寻址,而这两条指令的指令周期是一样的,均为2us(12.0M晶振);因此,其执行效果也完全一样。gPWM_HIGH_L、gPWM_HIGH_H、 gPWM_LOW_L、 gPWM_LOW_L 的取值可以在例程初始化或调速调控函数中随时修改;由于采用的是定频调宽法,例程修改中只要注意gPWM_HIGH+gPWM_LOW的值为PWM_CYCLE即可。这样,实现了占空比可变的同时,也有效的控制了输出PWM波的误差率。
最后的这一条结论再明显不过了:其输出PWM波形频率的误差率计算式为:24/(PWM_CYCLE+24)。
全文到此结束,欢迎大家指正,砖头拍下来我也接着 !
用户111930 2008-4-2 18:47