This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] LAUNCHXL-F280049C:使用 ePWM 模块生成双脉冲

Guru**** 2524550 points
Other Parts Discussed in Thread: C2000WARE, SYSCONFIG

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1322747/launchxl-f280049c-double-pulse-generation-using-the-epwm-module

器件型号:LAUNCHXL-F280049C
主题中讨论的其他器件:C2000WARESysConfig

您好!

我正在 尝试 使用 ePWM 模块生成单个双脉冲信号、用于驱动 MOSFET 双脉冲测试装置。 目标是 实现类似于下图所示的波形:  

我 认为 这应该 非常容易在 Launchpad 上实现。 但是、由于我是该开发平台的新手、因此我现在已经为该平台纠结了一段时间。  

我采用的方法依赖于 ePWM 跳闸区域和事件触发器子模块。 我可以 使用 SYSCFG 文件并使用 CMPA 和 CMPB 计数器比较来生成所需的波形、如图所示。 我正在使用  事件触发器子模块 在每个周期后生成一个中断。 我已  在 SYSCFG 文件中将 GPIO1配置为 INPUTXBAR 源(GPIO 配置为输入: 输入时启用推挽输出/上拉)。  其原理是 当中断产生时、在中断无效中处理、此时 GPIO0被切换、触发一次性 TZ1 (通过 XBAR)并强制 EPWM 输出为低电平状态。  

以下是借助各种 c2000ware 示例、C2000 ePWM 开发人员指南以及此论坛中发现的类似问题完成的工作:

#include "driverlib.h"
#include "device.h"
#include "board.h"

uint32_t  epwm1IntCount;

__interrupt void DPhandler(void);

void main(void)
{
    epwm1IntCount = 0U;
    Device_init();                  // Initialize device clock and peripherals
    Device_initGPIO();                  // Disable pin locks and enable internal pull-ups.
    Interrupt_initModule();         // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    Interrupt_initVectorTable();    // Initialize the PIE vector table with pointers to the shell Interrupt service Routines (ISR).

    Board_init();
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);                          // Disable sync(Freeze clock to PWM as well)
    EPWM_setSyncOutPulseMode(myEPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);    // ePWM1 SYNCO is generated on CTR=0

    Interrupt_enable(INT_EPWM1);
    EPWM_setInterruptEventCount(myEPWM1_BASE, 0U);
    Interrupt_register(INT_EPWM1, &DPhandler);
    EPWM_enableTripZoneInterrupt(myEPWM1_BASE, EPWM_TZ_INTERRUPT_OST);

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);   // Enable sync and clock to PWM

    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

    for(;;) // IDLE loop. Just sit and loop forever (optional):
    {
        asm ("  NOP");
    }
}

__interrupt void DPhandler(void)
{
    epwm1IntCount++; // Interrupt count

    GPIO_togglePin(myGPIO1); // trip TZ1
    EPWM_clearOneShotTripZoneFlag(myEPWM1_BASE, EPWM_TZ_OST_FLAG_OST1);
    EPWM_clearTripZoneFlag(myEPWM1_BASE, (EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_CBC));
    EPWM_clearTripZoneFlag(myEPWM1_BASE, (EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST));
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2); // acknowledge interrupt to continue
}

根据当前解决方案、即使配置了计时器周期以及 CMPA 和 CMPB 值、使得 pulse1应为10us、pulse2应为4us、二者之间相差3us、也会生成单个4.6us 脉冲。 下面是 EPWM 模块的.syscfg 配置。 TBCTR 配置为在同步事件之后从初始计数器值100开始递减、以确保动作限定器事件"时基计数器等于零"被挂接。  

 我的 方法是否也 适用? 如果能对此提供任何帮助,我将不胜感激。  

如前所述、现在我已经  使用.syscfg 文件配置了 EPWM、GPIO 和 INPUTXBAR。 如果我要 在.c 代码中配置 EPWM 占空比、那么 SYSCFG 如何发挥作用?  是否将覆盖在.syscfg 中进行的配置? 如果我想使用参数控制脉冲宽度、我在将来可能想做这件事。  

非常感谢您的帮助。

此致、

Juhani

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Juhani:

    非常感谢这篇文章的详细介绍、也很高兴能够使用到目前为止的一些现有资源!

    您的方法对我来说似乎是正确的、但您是否能够提供一些有关您看到的行为的示波器截图? (希望查看您的 PWM 信号以及用作跳闸源的 GPIO 信号、以便查看跳闸的时序、从而查看 ISR 的发生时序)。 如果您从0开始计数器并进行递增计数、您会有什么不同的行为吗?

    关于 sysconfig 和.c 代码的使用:

    • Board_init()函数用于调用 SysConfig 生成的代码;因此,根据应用程序代码中的位置,它将覆盖您编写的配置。 先前的 到 board_init()。
    • ^话虽如此、您可以同时使用 driverlib/bitfield/sysconfig、但不会出现物流问题。 只需注意代码的顺序/使用的函数、这样就不会覆盖之前配置的内容(这意味着 在调用 board_init ()后您可以更改配置、SysConfig 不会覆盖它)
      • 如果您不知道、则可以通过点击右上角的<>箭头并点击"board.c"文件来查看 SysConfig 生成的代码-这将在您更新 SysConfig 设置时实时显示代码更改。

    此致、

    艾里森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Allison:

    感谢您的快速响应。

    当  使用 示波器进一步研究系统的行为时、我注意到 TZ1始终会跳闸、即使 GPIO 在任何时候都没有切换。 实际上、切换 GPIO 似乎没有任何作用。 我还注意到、禁用 事件触发 EPWM 中断也根本不会影响输出。  当计数器从0开始递增计数时、行为没有区别。  

    这是当  EPWM 中断被禁用且 GPIO 在任何点都未切换时的输出结果。 我还注释了 以下代码中的中断配置命令:

    C1 (黄线)是被拉低的 EPWMA 输出、C2 (绿色)是用于跳闸的 GPIO 输出、C3 (红色)是 EPWMB 输出。 EPWMB 在动作限定器中配置为完全为 EPWMA、但在跳闸区域子模块中、会禁用 TZB 事件、这样输出不会因一次性跳闸而跳闸。  PWM 信号 看起来良好(高10us、低3us、高4us 重复)。  

    似乎是 TZ1跳闸、将 EPWMA 拉至低电平。 XBAR 输入源 GPIO 引脚也会以某种方式切换。 这些事件不会同时发生、两个事件看似随机时间发生。  

    以下是启用 ePWM 中断后的输出结果:

    启用 ePWM 中断似乎只影响一些时序。 EPWMA 的输出相同。  

    您是否有任何想法可能导致 TZ1行程?

    此致、

    Juhani

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Juhani:

    这使我认为 GPIO 可能存在一些配置问题。 能否 仔细检查一下您为每个信号使用的 GPIO? (例如、对于 EPWM1A 为 GPIO0、对于 EPWM1B 为 GPIO1等)、以及您正在作用域哪些引脚以及在 SysConfig 外设的 PinMux 面板中设置哪些引脚? 与我共享您的 SysConfig 文件可能会有所帮助。

    其他一些尝试事项:

    • 检查运行程序时是否看到中断计数增加。
    • 您是否曾尝试使用"step into"和"step overing"按钮浏览每行代码? 有时、在查看 CCS 窗口中的寄存器设置时这样做会很有用、可以在您逐步执行代码行时查看这些设置的实时变化、并确保按您所需的方式配置寄存器设置。
    • 您是否参考了 ePWM 跳匣区域 C2000Ware 示例? 如果是、是哪一个?

    此致、

    艾里森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Allison:

    非常感谢您的帮助。  你的建议给了我大量的考虑。  

    首先、我清除了错误的中断组。  EPWM1分配到组3。 我还需要通过在事件触发器子模块中启用寄存器中断处理程序并在 PIE 中启用中断来配置 ePWM 中断处理程序。

     当 GPIO 配置被 Board_init ()加载时, TZ1似乎会发生跳闸的问题。 出于某种原因、在我上次回复的屏幕截图中看不到这 一点、但启动程序时 GPIO 输出始终跳高电平。 这会导致一次性中断、 为了继续操作、需要确认该中断。

    正如我已注意到的、中断似乎会影响输出信号的一些时序。 为了 始终如一地实现10us 和4us 脉冲、我对其进行了更改、以便在定时器递减时 TBCTR=CMPC 时发生中断事件、并设置 CMPC、以便 在第二个脉冲设为低电平后立即触发比较事件。 出于某种原因、我无法使用 CMPA、它可能无法同时用于两个比较事件。  

    我   也会在此处发布工作代码和事件触发器中断配置、以防有人发现 它们有用:

    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    uint32_t  CTR0Count;
    
    __interrupt void DPhandler(void);
    
    void main(void)
    {
        CTR0Count = 0U;
        Device_init();                  // Initialize device clock and peripherals
        Device_initGPIO();              // Disable pin locks and enable internal pull-ups.
        Interrupt_initModule();         // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        Interrupt_initVectorTable();    // Initialize the PIE vector table with pointers to the shell Interrupt service Routines (ISR).
    
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);                          // Disable sync(Freeze clock to PWM as well)
        
        Board_init();
        
        // Board_init() causes a TZ1 trip, causing a one-shot interrupt which is needed to be acknowledged in order to continue
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); // acknowledge interrupt to continue
        
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);   // Enable sync and clock to PWM
    
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
        for(;;) // IDLE loop. Just sit and loop forever (optional):
        {
            asm ("  NOP");
        }
    }
    
    __interrupt void DPhandler(void)
    {
        CTR0Count++; // Interrupt count
    
        if (CTR0Count == 1) {
                GPIO_togglePin(myGPIO1); // trip TZ1
            }
        if (CTR0Count == 2) {
                GPIO_togglePin(myGPIO1); // trip TZ1
            }
        EPWM_clearOneShotTripZoneFlag(myEPWM1_BASE, EPWM_TZ_OST_FLAG_OST1);
        EPWM_clearTripZoneFlag(myEPWM1_BASE, (EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST));
        EPWM_clearEventTriggerInterruptFlag(myEPWM1_BASE);
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); // acknowledge interrupt to continue
    }

     

    此致、

    Juhani