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<N;k++) {sina[k]= sin(2*3.1416*k/N);}
但是有没有发现,这里的载波并不是那种有正有负的、并且幅值为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;k++) {sina[k]= sin(2*3.1416*k/N); sinb[k]= sin(2*3.1416*k/N);}
DINT; //关闭中断
InitPieCtrl(); //初始化中断控制
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();//初始化中断矢量表
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.EPWM1_INT = &epwm1_isr;
EDIS;
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; //先置0进行ePWM配置再置1
EDIS;
InitEPwm1Example();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; //看上一个注释
EDIS;
IER |= M_INT3;
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
for(;;){
__asm(" NOP");
}
}
void Gpio_Setup(void){
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0=1; //GPIO0配置为ePWM1A功能
GpioCtrlRegs.GPAMUX1.bit.GPIO1=1; //GPIO1配置为ePWM1B功能
EDIS;
}
void InitEPwm1Example(void){
// Setup TBCLK
EPwm1Regs.TBPRD = 25000; // 增减模式下为3KHz,自行计算
EPwm1Regs.TBPHS.half.TBPHS = 0; // Phase is 0
EPwm1Regs.TBCTR = 0; // 时基计数器清零
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
// Setup shadowing
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // CTR = Zero时CMPA从影子寄存器加载
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // CTR = Zero时CMPB从影子寄存器加载
// Set actions
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
// Interrupt where we will change the Compare Values
EPwm1Regs.ETSEL.bit.INTSEL= ET_CTR_PRD; // Select INT on PRD event
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1ST event
EPwm1Regs.CMPA.half.CMPA = 0x0C35;//随便给的初始值,去掉也没问题吧
}
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;
}
来源:oschina
链接:https://my.oschina.net/u/4362330/blog/4410375