一、EWPM模块简介

         PWM 是 Pulse Width Modulation 的缩写, 中文意思就是脉冲宽度调制, 简称&nasp;脉宽调制。 它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术, 其控制简单、 灵活和动态响应好等优点而成为电力电子技术最广泛应用的控制方式, 其应用领域包括测量, 通信, 功率控制与变换, 电动机控制、 伺服控制、 调光、 开关电源, 甚至某些音频放大器, 因此学习 PWM 具有十分重要的现实意义。PWM 是 Pulse Width Modulation 的缩写, 中文意思就是脉冲宽度调制, 简称脉宽调制。 它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术, 其控制简单、 灵活和动态响应好等优点而成为电力电子技术最广泛应用的控制方式, 其应用领域包括测量, 通信, 功率控制与变换, 电动机控制、 伺服控制、 调光、 开关电源, 甚至某些音频放大器, 因此学习 PWM 具有十分重要的现实意义。

         一个有效的 PWM 外设能够占用最少的 CPU 资源和中断, 但可以产生灵活配置的脉冲波形, 并且可以方便被理解与使用。 单周期的 PWM 波形很简单, 主要就是控制脉冲的周期, 脉冲的宽度, 脉冲起落的时间, 一个周期内的脉冲个数, 但事实是产生 PWM 波形时, 要结合实际应用, 每个要素都要顾及, 需要灵活配置, 涉及到强电控制与弱电控制的结合, 有一定的难度和技术门槛, 需要耐心的研究。F28335 的 ePWM 模块是个加强模块, 与 F2812 的 PWM 模块有较大不同, 在 F2812中, PWM 模块采用事件管理器控制, 与 eCAP 和 eQEP 共享定时器信号, 而 F28335中每个 ePWM 模块都是一个独立的小模块, 这样的体系结构更方便我们使用与理解。 每个 ePWM 模块由两路 ePWM 输出组成, 分别为 ePWMxA 和ePWMxB, 这一对 PWM输出, 可以配置成两路独立的单边沿 PWM 输出, 或者两路独立的但互相相对称的双边沿 PWM 输出, 或者一对双边沿非对称的 PWM 输出, 共有 6 对这样的 ePWM 块, 因为每对 PWM 模块中的两个 PWM 输出均可以单独使用, 所以也可以认为有12 路单路 ePWM, 除此之外还有 6 个 APWM, 这 6 个 APWM 通过 CAP 模块扩展配置,可以独立使用, 所以 F28335 最多可以有 18 路 PWM 输出。 每一组 ePWM 模块都包含以下 7 个模块: 时基模块 TB、 计数比较模块 CC、 动作模块 AQ、 死区产生模块DB、 PWM 斩波模块 PC、 错误联防模块 TZ、 时间触发模块 ET, 如下所示:

DSP TMS320F28335 EPWM输出pwm波形_数字输出


每组 PWM 模块主要的输入输出信号如下, 如下所示:

DSP TMS320F28335 EPWM输出pwm波形_数字输出_02


每组 ePWM 模块支持以下特点:

1, 专用 16 位时基计数器, 控制输出的周期和频率。

2, 两个互补对称 PWM 输出(ePWMxA 和 ePWMxB) 可以配置如下方式:

–两个独立的单边沿操作的 PWM 输出。

–两个独立的双边沿操作对称的 PWM 输出。

–一个独立的双边沿操作非对称的 PWM 输出。

3, 软件实现 PWM 信号异步控制。

4, 可编程的相位控制以支持超前或滞后其余的 PWM 模块

5, 逐周期硬件同步相位

6, 双边沿延时死区控制。

7, 可编程错误联防。

8, 产生错误时可以强制 PWM 输出高电平、 低电平或者高阻态。

9, 所有的事件都可以触发 CPU 中断和 ADC 开始转换信号。

10, 高频 PWM 斩波, 用于基于脉冲变压器的门极驱动。

二、驱动代码

void motor_init()
{
EALLOW;
//motor_pwm
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Disable TBCLK within the ePWM
SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // ePWM1
SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK = 1; // ePWM2

GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // Enable pull-up on GPIO0 (EPWM1A)
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // Enable pull-up on GPIO1 (EPWM1B)
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B

GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0; // Enable pull-up on GPIO2 (EPWM2A)
GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0; // Enable pull-up on GPIO3 (EPWM3B)
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; // Configure GPIO3 as EPWM2B
EDIS;

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
//EALLOW; // This is needed to write to EALLOW protected registers
//PieVectTable.EPWM1_INT = &epwm1_isr;
//EDIS; // This is needed to disable write to EALLOW protected registers

EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks
EDIS;

// Setup Sync
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // Pass through
// Allow each timer to be sync'ed
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm1Regs.TBPHS.half.TBPHS = 0;
EPwm1Regs.TBCTR = 0x0000; // Clear counter
EPwm1Regs.TBPRD = 15000;
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm1Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
EPwm1Regs.TBCTL.bit.CLKDIV=TB_DIV1;

// Setup shadow register load on ZERO
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

// Set Compare values
EPwm1Regs.CMPA.half.CMPA = 0; // Set compare A value
EPwm1Regs.CMPB = 0; // Set Compare B value

// Set actions
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count
EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM1B on Zero
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM1B on event B, up count

// Active Low PWMs - Setup Deadband
/* EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_LO;
EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
EPwm1Regs.DBRED = 100;
EPwm1Regs.DBFED = 100;*/

EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
EPwm1Regs.ETSEL.bit.INTEN = 0; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event


// Setup Sync
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // Pass through
// Allow each timer to be sync'ed
EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm2Regs.TBPHS.half.TBPHS = 0;
EPwm2Regs.TBCTR = 0x0000; // Clear counter
EPwm2Regs.TBPRD = 15000;
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm2Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;
EPwm2Regs.TBCTL.bit.CLKDIV=TB_DIV1;

// Setup shadow register load on ZERO
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

// Set Compare values
EPwm2Regs.CMPA.half.CMPA = 0; // Set compare A value
EPwm2Regs.CMPB = 0; // Set Compare B value

// Set actions
EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count
EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM1B on Zero
EPwm2Regs.AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM1B on event B, up count

// Active Low PWMs - Setup Deadband
/* EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_LO;
EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;
EPwm2Regs.DBRED = 100;
EPwm2Regs.DBFED = 100;*/

EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
EPwm2Regs.ETSEL.bit.INTEN = 0; // Enable INT
EPwm2Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event

EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced
EDIS;
}

void left_motor_forward(u16 pwmVal)
{
EPwm1Regs.CMPA.half.CMPA = pwmVal; //设置占空比
EPwm1Regs.CMPB = 0; //设置占空比
}
void left_motor_reversal(u16 pwmVal)
{
EPwm1Regs.CMPA.half.CMPA = 0; //设置占空比
EPwm1Regs.CMPB =pwmVal; //设置占空比
}
void right_motor_forward(u16 pwmVal)
{
EPwm2Regs.CMPA.half.CMPA = 0; //设置占空比
EPwm2Regs.CMPB =pwmVal; //设置占空比
}
void right_motor_reversal(u16 pwmVal)
{
EPwm2Regs.CMPA.half.CMPA = pwmVal; //设置占空比
EPwm2Regs.CMPB = 0; //设置占空比
}