1 ePWM模块介绍
1.1 ePWM脉冲宽度调制原理
ePWM是增强型脉冲宽度调制器(enhanced pulse width modulator)的缩写,该外设能够输出复杂的脉冲信号,且占用很小的CPU资源, 广泛应用于工业控制中,如电机控制技术。
脉冲宽度调制的原理是:冲量相等而形状不同的窄脉冲加载到具有惯性的环节上时,其效果基本相同(面积等效原理)。如下图所示,形状不同而冲量相等的四种窄脉冲信号,加载在下面所示的电路系统中,电流输出波形在上升段略有不同,但其下降段几乎完全相同,脉冲越窄,各输出波形的差异也就越小。
目前多数电力系统应用中采用正弦交流电,利用上述面积等效原理,可以用一系列脉冲信号等效产生正弦波形。如下图所示,将正弦波形等分成N份,且每份的面积用等幅的脉冲信号代替,保证每份正弦面积的中心线与脉冲信号的中心线相对应。
1.2 TMS28335的ePWM模块介绍
F2833x中ePWM模块共由6对ePWM子模块组成,ePWM1,ePWM2,ePWM3,ePWM4,ePWM5,ePWM6。每个子模块由两路ePWM输出,如ePWM1的输出ePWM1A和ePWM1B。每组ePWM模块的输入输出信号如下:
- PWM输出信号(ePWMxA和ePWMxB):PWM输出引脚与GPIO引脚复用,具体使用需参照GPIO引脚配置。
- 时间基础同步输入(ePWMxSYNCI)、输出信号(ePWMxSYNCO):每个ePWM模块都可以根据需要被配置为使用同步信号,或忽略其同步输入成为独立单元。时钟同步输入仅由ePWM1引脚产生,ePWM1的同步输出也与第一个捕获模块eCAP1的同步信号相连。
- 错误联防信号(TZ1~TZ6 ):当外部被控单元发生错误,如IGBT过电压等,这些输入信号为ePWM模块发出错误警告。
- ADC启动信号及外设总线,介绍略。
每一组ePWM模块都包含以下7个子模块:时基模块TB、比较计数器CC、动作模块AQ、死区产生模块DB、PWM斩波模块PC、事件触发模块ET、错误联防TZ。
七个子模块起作用分别是:
- 时钟信号TB经过时基模块的配置产生时基信号,用于设定PWM波形的周期
- 比较模块CC通过设置比较对象,用于设定PWM波形的脉冲宽度
- 动作模块AQ限定PWM输出状态即脉冲波形的起落
- 死区模块DB将同组内的互补输出PWM进行边沿延迟
- 斩波模块PC进行第一个脉冲宽度设置和后级脉冲占空比调整以适应脉冲变压器的门极驱动控制
- 事件触发ET用于选择触发事件类型(INT或SOC)以及触发信号的产生
- 错误联防TZ接收功率器件的错误信号,以强制复位PWM信号
2 ePWM的时基模块TB
TB模块的主要作用是为ePWM模块提供时基事件信号,如上图所示的CTR_ZERO,CTR_PRD,CTR_Dir,并且基于EPWMxSYNCI、EPWMxSYNCO以及相位寄存器控制计数器在不同模块之间的同步与相位偏差。
TB模块需要注意的由以下几点:
- 通过设置TBCTL[PRDLD]的值,周期寄存器TBPRD加载可以选择是否从Shadow加载。TBCTL[PRDLD]=0时,当时基计数器为0时,周期寄存器TBPRD才从Shadow寄存器加载,读或写周期寄存器的值都是在Shadow寄存器间接操作;TBCTL[PRDLD]=1时,周期寄存器TBPRD直接从Active读取,读或写周期寄存器的值都是从Active里直接操作。Active(活动)寄存器是工作寄存器,控制着硬件,也可以响应由硬件引起的相关事件,Shadow(影子)寄存器为活动寄存器提供一个暂时存放地址,不能直接影响硬件控制,只有当满足一定条件时,如实际计数器计数到0,Shadow寄存器的值才会传给活动寄存器,这样做主要是防止软件寄存器与硬件不同步从出现问题。
- 周期计数器从相位寄存器加载,TBCTL[PHSEN]=1时,当输入信号触发或者软件信号直接强制触发(TBCTL[SWFSYNC] = 1,注意TBCTL[SYNCOSEL] = 0时软件信号强制触发才生效)。当选择增、减计数方式时,周期寄存器从相位寄存器加载涉及到方向的选择,当TBCTL[PHSDIR]=1时,表示从相位寄存器加载计数后是增计数,否则为减计数,如下图所示:
- 关于EPWMxSYNCO可以通过TBCTL[SYNCOSEL]来选择是来自于何种信号,有EPWMxSYNCI、CTR=ZERO、CTR=CMPB和不使用同步输出。且多个ePWM中前一个的输出作为下一个的输入。第一个ePWM的EPWMxSYNCI通过引脚输入。
3 ePWM实例1
下列代码实例通过配置ePWM模块实现中断触发,并在触发函数中计数,比较触发次数。代码主要用到了TB模块和ET模块的相关寄存器。代码的结果是计数值1~6,1/4/5/6的计数值相等,2的计数值约等于1/4/5/6的二分之一,3的计数值约等于1/4/5/6的三分之一。
void main(void)
{
int i;
// 初始化系统控制
InitSysCtrl();
// 禁止CPU中断
DINT;
// 初始化PIE控制寄存器到期默认状态
InitPieCtrl();
// 禁止CPU中断和清除所有CPU中断标志位
IER = 0x0000;
IFR = 0x0000;
// 初始化PIE中断向量表
InitPieVectTable();
//配置ePWM模块的PIE中断
EALLOW;
PieVectTable.EPWM1_INT = &epwm1_timer_isr;
PieVectTable.EPWM2_INT = &epwm2_timer_isr;
PieVectTable.EPWM3_INT = &epwm3_timer_isr;
PieVectTable.EPWM4_INT = &epwm4_timer_isr;
PieVectTable.EPWM5_INT = &epwm5_timer_isr;
PieVectTable.EPWM6_INT = &epwm6_timer_isr;
EDIS;
//初始化ePWM处理
InitEPwmTimer();
// 用户代码
// 中断发生计数器
EPwm1TimerIntCount = 0;
EPwm2TimerIntCount = 0;
EPwm3TimerIntCount = 0;
EPwm4TimerIntCount = 0;
EPwm5TimerIntCount = 0;
EPwm6TimerIntCount = 0;
// 使能CPU中断线3
IER |= M_INT3;
// 使能ePWM1~6的 INT中断
PieCtrlRegs.PIEIER3.bit.INTx1 = PWM1_INT_ENABLE;
PieCtrlRegs.PIEIER3.bit.INTx2 = PWM2_INT_ENABLE;
PieCtrlRegs.PIEIER3.bit.INTx3 = PWM3_INT_ENABLE;
PieCtrlRegs.PIEIER3.bit.INTx4 = PWM4_INT_ENABLE;
PieCtrlRegs.PIEIER3.bit.INTx5 = PWM5_INT_ENABLE;
PieCtrlRegs.PIEIER3.bit.INTx6 = PWM6_INT_ENABLE;
// 使能全局中断
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// Step 6. IDLE loop. Just sit and loop forever (optional):
for(;;)
{
asm(" NOP");
for(i=1;i<=10;i++)
{}
}
}
void InitEPwmTimer()
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // 停止时基计时器时钟
EDIS;
// 设置同步输出信号,将ePWM1~6的同步输入信号均设置为同步输入信号触发
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
EPwm5Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
//计数寄存器装载相位寄存器使能位 当同步信号到来时,计数寄存器装载相位寄存器的值
EPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE;
EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE;
EPwm3Regs.TBCTL.bit.PHSEN = TB_ENABLE;
EPwm4Regs.TBCTL.bit.PHSEN = TB_ENABLE;
EPwm5Regs.TBCTL.bit.PHSEN = TB_ENABLE;
EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE;
//设置ePWM1~6各相位寄存器的值,同步信号有效时加载该值
EPwm1Regs.TBPHS.half.TBPHS = 100;
EPwm2Regs.TBPHS.half.TBPHS = 100;
EPwm3Regs.TBPHS.half.TBPHS = 100;
EPwm4Regs.TBPHS.half.TBPHS = 100;
EPwm5Regs.TBPHS.half.TBPHS = 100;
EPwm6Regs.TBPHS.half.TBPHS = 100;
EPwm1Regs.TBPRD = PWM1_TIMER_TBPRD; //时基计时器周期数设置为8192
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; //时基计数器计数模式为向上计数,那么计数周期T=(TBPRD+1) * TBCLK
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; //CTR=0信号发生时触发INT中断
EPwm1Regs.ETSEL.bit.INTEN = PWM1_INT_ENABLE; // ePWM1对应的INT中断使能
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // 每1个事件触发一次INT中断
EPwm2Regs.TBPRD = PWM2_TIMER_TBPRD;
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
EPwm2Regs.ETSEL.bit.INTEN = PWM2_INT_ENABLE;
EPwm2Regs.ETPS.bit.INTPRD = ET_2ND; // 每2个事件触发一次INT中断
EPwm3Regs.TBPRD = PWM3_TIMER_TBPRD;
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
EPwm3Regs.ETSEL.bit.INTEN = PWM3_INT_ENABLE;
EPwm3Regs.ETPS.bit.INTPRD = ET_3RD; // 每3个事件触发一次INT中断
EPwm4Regs.TBPRD = PWM4_TIMER_TBPRD;
EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm4Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
EPwm4Regs.ETSEL.bit.INTEN = PWM4_INT_ENABLE;
EPwm4Regs.ETPS.bit.INTPRD = ET_1ST; // 每1个事件触发一次INT中断
EPwm5Regs.TBPRD = PWM5_TIMER_TBPRD;
EPwm5Regs.TBCTL.bit.CTRMODE= TB_COUNT_UP;
EPwm5Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
EPwm5Regs.ETSEL.bit.INTEN = PWM5_INT_ENABLE;
EPwm5Regs.ETPS.bit.INTPRD = ET_1ST; // 每1个事件触发一次INT中断
EPwm6Regs.TBPRD = PWM6_TIMER_TBPRD;
EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;
EPwm6Regs.ETSEL.bit.INTEN = PWM6_INT_ENABLE;
EPwm6Regs.ETPS.bit.INTPRD = ET_1ST; // 每1个事件触发一次INT中断
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // 启动时基计时器时钟
EDIS;
}