DSP新手,研究了一下午,在这里做个总结,希望对其他刚接触DSP的新手也能有所帮助。
首先要明白SPWM波是什么。
SPWM波实际上就只有2种电平,而且其频率一般是你自己给定的,所以难点在于如何调节每个周期内的占空比,这里采用的是双极性调制法。
先说总体思路:以TBCTR为载波,以CMPA为调制波,并且让CMPA的值不断更新(中断方式),就可以在ePWMxA产生SPWM波。

看了一些资料的你(没看就去看吧),应该能了解到ePWM模块的TB寄存器是设置频率的,CMPA和CMPB是设置占空比的,AQ是设置触发方式的。
如果设置好TB,那么就可以使得ePWM模块的计数器TBCTR从0上升到TBPRD然后下降到0,以此得到三角调制波,那就必须有
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
此外还要设置AQ,保证是调制波大于载波的时候,输出高电平:
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // Set PWM1A on event A, down count
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM1B on event B, up count
EPwm1Regs.AQCTLB.bit.CBD = AQ_SET; // Set PWM1B on event B, down count
而载波要怎么获得呢?Easy,写函数表即可。形式就是 sin(2π*i/N),i=0,1,…,N-1
float sina[256];
for(k=0;k
但是有没有发现,这里的载波并不是那种有正有负的、并且幅值为1的形式呢?我们能用的载波和图中的载波看起来就好像是标准载波加1并且乘以TBPRD/2得到的对吧?既然没法对载波进行变换,那就对调制波进行同样的变换,让调制波为TBPRD*(1+ M*sin(wt))/2,M为调制比,这样得到的调制结果也会是相同的,这里很关键。
当然最关键的地方就是中断了,这一段意思很明白,就是根据正弦表不断更新CMPA和CMPB的值,这就相当于一个阶梯状的调制波TBPRD*(1+ M*sin(wt))/2:
interrupt void epwm1_isr(void){ EPwm1Regs.CMPA.half.CMPA=EPwm1Regs.TBPRD*((1.0+M*sina[i])/2.0); EPwm1Regs.CMPB=EPwm1Regs.TBPRD*((1.0+M*sinb[i])/2.0); i++; if (i>=N){ i=0; } EPwm1Regs.ETCLR.bit.INT = 1; //写1对ETFLG[INT]状态标志位清零才能进行下一次中断 PieCtrlRegs.PIEACK.all=PIEACK_GROUP3; }
完整代码如下,烧录后,可以在PWM1引脚观察到SPWM波输出,关于频率的设置(TB的设置)这里就不多说了:
#include "DSP2833x_Project.h" #include "math.h" void InitEPwm1Example(void); void Gpio_Setup(void); interrupt void epwm1_isr(void); int i,k=0; float M=0.8;//调制比 int N=256; //采样点数 float sina[256]; float sinb[256]; void main(void) { InitSysCtrl(); //初始化系统控制 InitEPwm1Gpio(); Gpio_Setup(); //子函数,Gpio口设置 for(k=0;k
=N){ i=0; } EPwm1Regs.ETCLR.bit.INT = 1; //写1对ETFLG[INT]状态标志位清零才能进行下一次中断 PieCtrlRegs.PIEACK.all=PIEACK_GROUP3; }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/175819.html原文链接:https://javaforall.net
