日志档案

发表于 2007-1-27 6:04:47

3

标签: Proteus  

51单片机软模PWM误差率之深入再研究--基于Keil、Proteus仿真调试

本人不揣冒昧,两天前写了个“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)。

 

全文到此结束,欢迎大家指正,砖头拍下来我也接着 !

系统分类: 单片机   |   用户分类: 画饼充饥   |   来源: 原创   |   【推荐给朋友】

    阅读(1054)    回复(1)  

投一票您将和博主都有获奖机会!