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.

[参考译文] TMS320F28374D:PWM 全局加载问题

Guru**** 2430620 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1062968/tms320f28374d-pwm-global-load-issue

器件型号:TMS320F28374D

各位专家、您好!

我的客户遇到有关全局加载的问题。 以下是他的设置:

 EPWM1、 EPWM2、 EPWM7、 EPWM8是一个组;

2.计数器: 上数模式;

3.启用 TBPRDCMPACMPB 的影子模式;

4.启用 TBPRD_TBPRDHRCMPA_CPMAHRCMPB_CMPBHRAQCTLA_AQCTLA2AQCTLB_AQCTLB2的全局模式;

5. CNT=PRD 时的全局加载;

6.启用  全局加载的 OSHTMODE;

在其      ↓中、他需要将 EPWM7、EPWM8的 AQCTLA 从 ZRO↑、CAU↑、CBU↓更改为 ZRO ↑、CAU ↓、CBU。 但是、当 ZRO 应该被设定为低电平、但保持高电平时、随机发生、如下所示:

如上图所示:在第二个 CNT=PRD、AQCTLx、TBPRD、CMPA、CMPB 更新。  因此、在第二个 CNT=ZRO 时、它应该是一个下拉驱动器、但结果仍然保持高电平。  

请就此问题提供帮助、谢谢!

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

    尊敬的 Angela:

    感谢您提出详细的问题。 是否知道 GLDCTL2寄存器中的 OSHTLD 位是否正在更新以导致更新?

    如果使用 driverlib、则会转换为以下函数: ePWM_setGlobalLoadOneShotLatch()

    同样、为了使用与上面项目4和6分开的全局加载功能、需要将 GLDCTL 的 GLD 位设置为1。

    这将转换 为 driverlib 中的 ePWM_enableGlobalLoad()。

    此外、您能否描述更新的位置? 计时器 ISR、ADC ISR?

    此致、

    Marlyn

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

    您好、Marlyn、

    GLD 位已设置为1。 所有更新都在计时器中断中。

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

    尊敬的 Angela:

    此问题是否仅在 EPWM7/8上出现? 它是否仅在一次性加载后的下一个周期发生、还是 AQCTLA 操作从未更新?

    您能否提供一些代码、以便我们能够复制我们一侧的代码?

    我使用 EPWM1/2进行了简短测试、并且 AQCTL 设置更新:

    //
    // Included Files
    //
    #include "F28x_Project.h"
    
    
    //
    // Globals
    //
    uint16_t EPwm1TimerIntCount;
    uint16_t EPwm2TimerIntCount;
    
    //
    // Function Prototypes
    //
    void InitEPwm1Example(void);
    void InitEPwm2Example(void);
    __interrupt void epwm1_isr(void);
    __interrupt void epwm2_isr(void);
    __interrupt void cpu_timer0_isr(void);
    
    //
    // Main
    //
    void main(void)
    {
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    //
        InitSysCtrl();
    
    //
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xD_Gpio.c file and
    // illustrates how to set the GPIO to its default state.
    //
    //    InitGpio();
    
    //
    // enable PWM1, PWM2
    //
        CpuSysRegs.PCLKCR2.bit.EPWM1=1;
        CpuSysRegs.PCLKCR2.bit.EPWM2=1;
    
    
    //
    // For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
    // These functions are in the F2837xD_EPwm.c file
    //
        InitEPwm1Gpio();
        InitEPwm2Gpio();
    
    //
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    //
        DINT;
    
    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xD_PieCtrl.c file.
    //
        InitPieCtrl();
    
    //
    // Disable CPU interrupts and clear all CPU interrupt flags:
    //
        IER = 0x0000;
        IFR = 0x0000;
    
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xD_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
    //
        InitPieVectTable();
        InitCpuTimers();
    
    //
    // 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;
        PieVectTable.EPWM2_INT = &epwm2_isr;
        PieVectTable.TIMER0_INT = &cpu_timer0_isr;
        EDIS;   // This is needed to disable write to EALLOW protected registers
    
    
    //
    // Configure CPU-Timer 0 to __interrupt every 500 milliseconds:
    // 60MHz CPU Freq, 50 millisecond Period (in uSeconds)
    //
        ConfigCpuTimer(&CpuTimer0, 60, 500000);
    
    //
    // Step 4. Initialize the Device Peripherals:
    //
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =0;
        EDIS;
    
        InitEPwm1Example();
        InitEPwm2Example();
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =1;
        EDIS;
    
    //
    // Start the timer
    //
        CpuTimer0Regs.TCR.all = 0x4001;
    
    //
    // Step 5. User specific code, enable interrupts:
    // Initialize counters:
    //
        EPwm1TimerIntCount = 0;
        EPwm2TimerIntCount = 0;
    
    //
    // Enable CPU INT3 which is connected to EPWM1-2 INT and INT1 for Timer 0
    //
        IER |= M_INT3;
        IER |= M_INT1;
    
    //
    // Enable EPWM INTn in the PIE
    //
        PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
        PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
        PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    
    //
    // Enable global Interrupts and higher priority real-time debug events:
    //
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
    //
    // Step 6. IDLE loop. Just sit and loop forever (optional):
    //
        for(;;)
        {
            asm ("          NOP");
        }
    }
    
    
    //
    // cpu_timer0_isr - CPU Timer0 ISR
    //
    __interrupt void cpu_timer0_isr(void)
    {
       CpuTimer0.InterruptCount++;
    
       //
       // Update the AQCTL settings of EPWM1 and EPWM2
       //
       EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;          // Clear PWM1A on Zero
       EPwm2Regs.AQCTLA.bit.ZRO = AQ_CLEAR;          // Clear PWM1A on Zero
    
       // EPWM1 and EPWM2 are linked so this will udpate both
       EALLOW;
       EPwm1Regs.GLDCTL2.bit.OSHTLD = 1;               // Enable re-load of Actions
       EDIS;
    
       //
       // Acknowledge this __interrupt to receive more __interrupts from group 1
       //
       PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }
    
    //
    // epwm1_isr - EPWM1 ISR
    //
    __interrupt void epwm1_isr(void)
    {
        EPwm1TimerIntCount++;
    
        //
        // Clear INT flag for this timer
        //
        EPwm1Regs.ETCLR.bit.INT = 1;
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }
    
    //
    // epwm2_isr - EPWM2 ISR
    //
    __interrupt void epwm2_isr(void)
    {
        EPwm2TimerIntCount++;
    
        //
        // Clear INT flag for this timer
        //
        EPwm2Regs.ETCLR.bit.INT = 1;
    
        //
        // Acknowledge this interrupt to receive more interrupts from group 3
        //
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }
    
    
    //
    // InitEPwm1Example - Initialize EPWM1 configuration
    //
    void InitEPwm1Example()
    {
    
        //
        // Global Loading Settings
        //
        EALLOW;
        EPwm1Regs.GLDCTL.bit.GLD = 1;               // Enable Global Shadow to Active Load
        EPwm1Regs.GLDCTL.bit.GLDMODE = 1;           // Load on Counter = PRD
        EPwm1Regs.GLDCTL.bit.OSHTMODE = 1;          // One-Shot mode is active
    
        //
        // Global Load Parameters
        //
        EPwm1Regs.GLDCFG.bit.AQCTLA_AQCTLA2 = 1;
        EPwm1Regs.GLDCFG.bit.AQCTLB_AQCTLB2 = 1;
        EPwm1Regs.GLDCFG.bit.TBPRD_TBPRDHR = 1;
        EPwm1Regs.GLDCFG.bit.CMPA_CMPAHR = 1;
        EPwm1Regs.GLDCFG.bit.CMPB_CMPBHR = 1;
        EDIS;
    
        EPwm1Regs.TBPRD = 6000;                       // Set timer period
        EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;           // Phase is 0
        EPwm1Regs.TBCTR = 0x0000;                     // Clear counter
    
        //
        // Setup TBCLK
        //
        EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;     // Count up
        EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV4;       // Clock ratio to SYSCLKOUT
        EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV4;
    
        //
        // Setup compare
        //
        EPwm1Regs.CMPA.bit.CMPA = 5000;
        EPwm1Regs.CMPB.bit.CMPB = 1000;
    
        EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;    // Load registers every ZERO
        EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
        EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
    
        //
        // Set actions
        //
        EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;            // Set PWM1A on CAU
        EPwm1Regs.AQCTLA.bit.CBU = AQ_CLEAR;          // Clear PWM1A on CBU
        EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
    
        //
        // Interrupt
        //
        EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;    // Select INT on Zero event
        EPwm1Regs.ETSEL.bit.INTEN = 1;               // Enable INT
        EPwm1Regs.ETPS.bit.INTPRD = ET_3RD;          // Generate INT on 3rd event
    
        EALLOW;
        EPwm1Regs.GLDCTL2.bit.OSHTLD = 1;           // Load shadow to active for initialization
        EDIS;
    }
    
    //
    // InitEPwm2Example - Initialize EPWM2 configuration
    //
    void InitEPwm2Example()
    {
    
        EPwm2Regs.TBPRD = 6000;                       // Set timer period
        EPwm2Regs.TBPHS.bit.TBPHS = 0x0000;           // Phase is 0
        EPwm2Regs.TBCTR = 0x0000;                     // Clear counter
    
        //
        // Setup TBCLK
        //
        EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;     // Count up
        EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
        EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV4;       // Clock ratio to SYSCLKOUT
        EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV4;          // Slow just to observe on
                                                       // the scope
    
        //
        // Setup compare
        //
        EPwm2Regs.CMPA.bit.CMPA = 5000;
        EPwm2Regs.CMPB.bit.CMPB = 1000;
    
        EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;    // Load registers every ZERO
        EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
        EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
    
        //
        // Global Loading Settings
        //
        EALLOW;
        EPwm2Regs.GLDCTL.bit.GLD = 1;               // Enable Global Shadow to Active Load
        EPwm2Regs.GLDCTL.bit.GLDMODE = 1;           // Load on Counter = PRD
        EPwm2Regs.GLDCTL.bit.OSHTMODE = 1;          // One-Shot mode is active
    
        //
        // Global Load Parameters
        //
        EPwm2Regs.GLDCFG.bit.AQCTLA_AQCTLA2 = 1;
        EPwm2Regs.GLDCFG.bit.AQCTLB_AQCTLB2 = 1;
        EPwm2Regs.GLDCFG.bit.TBPRD_TBPRDHR = 1;
        EPwm2Regs.GLDCFG.bit.CMPA_CMPAHR = 1;
        EPwm2Regs.GLDCFG.bit.CMPB_CMPBHR = 1;
        EDIS;
    
        //
        // Set actions
        //
        EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;            // Set PWM2A on CAU
        EPwm2Regs.AQCTLA.bit.CBU = AQ_CLEAR;          // Clear PWM2A on CBU
        EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM2A on Zero
    
        //
        // Interrupt
        //
        EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
        EPwm2Regs.ETSEL.bit.INTEN = 1;                // Enable INT
        EPwm2Regs.ETPS.bit.INTPRD = ET_3RD;           // Generate INT on 3rd event
    
    
        EALLOW;
        EPwm2Regs.GLDCTL2.bit.OSHTLD = 1;           // Load shadow to active for initialization
        EDIS;
    
        //
        // Linking
        //
        EPwm2Regs.EPWMXLINK.bit.GLDCTL2LINK = 0;   // Link to ePWM1
        EPwm2Regs.EPWMXLINK.bit.CMPALINK = 0;      // Link to ePWM1
        EPwm2Regs.EPWMXLINK.bit.CMPBLINK = 0;      // Link to ePWM1
        EPwm2Regs.EPWMXLINK.bit.TBPRDLINK = 0;     // Link to ePWM1
    }

    此致、

    Marlyn

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

    您好、Marlyn、

    只要在中断中更改任何 EPWM 模块的 AQCTLA、它不仅会在 EPWM7/8上以间歇间隔发生。 看起来 AQCTLA 在某个时候不会更新、并且是零星的、AQCTLA 在大多数时间通常都会更新。

    很抱歉、客户无法向我们提供源代码。 但是、如果需要、它们可以提供深入的信息或进一步的测试。

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

    是否根据需要更新全局加载中的所有其他项?  您能否 检查以了解客户如何确认 AQCTLA 未更新?

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

    你好、Nima、

    黄色波形为 EPWM7_A;绿色波形为 EPWM8_A  EPWM7_A 和 EPWM8_A 是死区时间为150ns 的上桥和下桥臂驱动器。  EPWM7.EPWM8为全增模式。  

    EPWM7:ZROCAUCBU↓,EPWM7_CMPB- EPWM7_CMPA = Ton。

    EPWM8:如果 CMPB > TBPRD、 ZROCAUCBU↓,EPWM8_CMPB = EPWM8_CMPBTBPRDPWM8_CMPA- EPWM8_CMPB = Toff

            如果 CMPBTBPRD、 ZROCAUCBU↓,EPWM8_CMPB = EPWM8_CMPB1、 EPWM8_CMPB - EPWM8_CMPA = TOFF

    所有操作 每40k 更新一次。  如果 CMPA 和 CMPB 值不正确、则应持续25us (40k)。  如下面的图1所示、如果更新成功、那么第二个 ZRO 应该被设定为低电平并且不会发生直通。  第二次 ZRO 可能仍然被设定为高电平(更新无效)并导致传递。  然后、后续波形正常(图2)

    图1:

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

    您能否捕获发生错误时的 CMPA/CMPB 值是多少?  

    PRD 始终相同。

    NIMA

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

    你好、Nima、

    由于开关频率太高、而且偶尔也会出现此问题、因此很难捕获 CMPA 和 CMPB。 也许我们必须使用另一种方法来找出根本原因。

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

    捕获这些值的方法是:

    1.设置缓冲区以捕获 CMPA/CMPB、操作等(20个左右深)

    2.设置 ECAP 以捕获 EPWM 信号的高电平时间、并在检测到极长脉冲时、生成和 ESTOP0并读取捕获的缓冲区中的值。

    NIMA