DSP TMS320F28335 EPWM输出pwm波形

一、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, 如下所示:
在这里插入图片描述
每组 PWM 模块主要的输入输出信号如下, 如下所示:
在这里插入图片描述
每组 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;  //设置占空比
}


版权声明:本文为CSDN博主「小灰灰搞电子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_15181569/article/details/120541486

生成海报
点赞 0

小灰灰搞电子

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

RT-Thread Studio移植LAN8720A驱动

RTT网络协议栈驱动移植(霸天虎) 1、新建工程 ​ 工程路径不含中文路径名,工程名用纯英文不含任何符号。 2、用CubeMx配置板子外设 2.1、配置时钟 ​ 按照自己板子配置相应时钟。

ESP8266 无限重启踩坑

最近做了一个电子墨水屏万年历,在移植屏幕代码时遇到了esp8266无限软复位的问题,如果你的串口打印是以下图片所示,那么恭喜你问题解决了。 造成软复位的原因是因为,程序里有死循环&#xf

Renode应用:在RISC-V核上运行FreeRTOS

本篇记录通过Renode在RISC-V核上运行FreeRTOS demo的情况。本来不准备写这一篇,但是发现近期工作学习密度实在太大,上周工作的中间结果这周竟然完全想不起来了,不得不又花了一些时间从头摸

Lin总线通信在STM32作为主机代码以及从机程序

距离上次做资料准备已经过去六天了。最近在学车,上周末就没有开电脑。这周开始进行了Lin通信的代码整理,目前是可以正常通信的了,采用的是增强型校验方式。后期再进一步跟进研究。。。更新一博,留