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.

[参考译文] TMS320F280025C:为 ePWM 使用具有两倍速度的 DMA

Guru**** 2390735 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1460481/tms320f280025c-use-dma-for-epwm-with-twice-the-speed

器件型号:TMS320F280025C

工具与软件:

您好!

我需要能够使用 DMA 运行 ePWM 模块、但 速度要快两倍。 后台情况是、我想使用 DMA 更新 ePWM 模块、以实现中心对齐的 PWM。  

FOC (场定向控制)使用大约20kHz 完成、PWM 为40kHz。 现在、要计算高速应用的相位延迟、DMA 应该已经包含4组 PWM。 因此、我也希望中心对齐 PWM 的更新位于中间。

我已经在 TI 示例中尝试了 epwm_ex9_dma 示例、但我无法实现。 有什么想法如何做到这一点吗?

EDIT1:  我曾在第一步尝试在每个 PWM 周期中更新 DMA、并将 FOC ISR 的速度减半、但无法实现:

EPWM INIT (来自通用电机控制):

    // USER_M1_NUM_PWM_TICKS_PER_ISR_TICK = 2        
           
    uint16_t       pwmPeriodCycles = (uint16_t)(USER_M1_PWM_TBPRD_NUM);
    uint16_t       pwmPeriodBCCycles = (uint16_t)(USER_M1_BC_TBPRD_NUM);
    uint16_t       numPWMTicksPerISRTick = USER_M1_NUM_PWM_TICKS_PER_ISR_TICK;
        
        // setup the Time-Base Control Register (TBCTL)
        EPWM_setTimeBaseCounterMode(obj->pwmHandle[cnt],
                                    EPWM_COUNTER_MODE_UP_DOWN);

        EPWM_disablePhaseShiftLoad(obj->pwmHandle[cnt]);

//        EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_SHADOW_LOAD); //EPWM_PERIOD_SHADOW_LOAD //EPWM_PERIOD_DIRECT_LOAD
        EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_SHADOW_LOAD); //EPWM_PERIOD_SHADOW_LOAD //EPWM_PERIOD_DIRECT_LOAD

        EPWM_enableSyncOutPulseSource(obj->pwmHandle[cnt],
                                      EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);

        EPWM_setClockPrescaler(obj->pwmHandle[cnt], EPWM_CLOCK_DIVIDER_1,
                                 EPWM_HSCLOCK_DIVIDER_1);

        EPWM_setCountModeAfterSync(obj->pwmHandle[cnt],
                                   EPWM_COUNT_MODE_UP_AFTER_SYNC);

        EPWM_setEmulationMode(obj->pwmHandle[cnt], EPWM_EMULATION_FREE_RUN);

        // setup the Timer-Based Phase Register (TBPHS)
        EPWM_setPhaseShift(obj->pwmHandle[cnt], 0);

        // setup the Time-Base Counter Register (TBCTR)
        EPWM_setTimeBaseCounter(obj->pwmHandle[cnt], 0);

        // setup the Time-Base Period Register (TBPRD)
        // set to zero initially
        EPWM_setTimeBasePeriod(obj->pwmHandle[cnt], 0);

        // setup the Counter-Compare Control Register (CMPCTL)
        EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO); //EPWM_COMP_LOAD_ON_CNTR_ZERO

        EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

        EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                             EPWM_COUNTER_COMPARE_C,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

        EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                             EPWM_COUNTER_COMPARE_D,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
                // setup the Action-Qualifier Output A Register (AQCTLA)
        EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

        EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);

        EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);

        EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
                 // setup the Dead-Band Generator Control Register (DBCTL)
        EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, true);
        EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, true);

        // select EPWMA as the input to the dead band generator
        EPWM_setRisingEdgeDeadBandDelayInput(obj->pwmHandle[cnt],
                                             EPWM_DB_INPUT_EPWMA);

        // configure the right polarity for active high complementary config.
        EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt],
                                      EPWM_DB_RED,
                                      EPWM_DB_POLARITY_ACTIVE_HIGH);
                 EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt],
                                      EPWM_DB_FED,
                                      EPWM_DB_POLARITY_ACTIVE_LOW);
                // setup the Dead-Band Rising Edge Delay Register (DBRED)
        EPWM_setRisingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBRED_CNT);

        // setup the Dead-Band Falling Edge Delay Register (DBFED)
        EPWM_setFallingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBFED_CNT);
                // setup the PWM-Chopper Control Register (PCCTL)
        EPWM_disableChopper(obj->pwmHandle[cnt]);

        // setup the Trip Zone Select Register (TZSEL)
        EPWM_disableTripZoneSignals(obj->pwmHandle[cnt], HAL_TZSEL_SIGNALS_ALL);
        
            // setup the Event Trigger Selection Register (ETSEL)
    EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO); //EPWM_INT_TBCTR_ZERO

    EPWM_enableInterrupt(obj->pwmHandle[0]);

    //Initial ADC trigger --> used for FOC
    EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC); //EPWM_SOC_TBCTR_D_CMPC
    EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
    
        EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMTicksPerISRTick);

    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A,
                                    numPWMTicksPerISRTick);
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B,
                                    numPWMTicksPerISRTick);
                                    
        // setup the Event Trigger Clear Register (ETCLR)
    EPWM_clearEventTriggerInterruptFlag(obj->pwmHandle[0]);
    EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_A);
    EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_B);

    // since the PWM is configured as an up/down counter, the period register is
    // set to one-half of the desired PWM period
    EPWM_setTimeBasePeriod(obj->pwmHandle[0], pwmPeriodCycles);
    EPWM_setTimeBasePeriod(obj->pwmHandle[1], pwmPeriodCycles);
    EPWM_setTimeBasePeriod(obj->pwmHandle[2], pwmPeriodCycles);

    // write the PWM data value  for ADC trigger
    EPWM_setCounterCompareValue(obj->pwmHandle[0], EPWM_COUNTER_COMPARE_C, 10);
    
    

DMA 初始化:

    //
    // DMA CH4
    //
    DMA_configAddresses(DMA_CH4_BASE, (uint16_t *)(MTR1_PWM_U_BASE + EPWM_O_CMPA),
                        dma_epwm_config.dmaConfigsCycleU);
    DMA_configBurst(DMA_CH4_BASE, 2, 1, 1); //4 bursts --> One for for each up and down of the center aligned PWM
    DMA_configTransfer(DMA_CH4_BASE, 1, 1, -2); //4 Transfers, CMPAHR  ,   CMPA   ,   CMPBHR  ,   CMPB
    DMA_configMode(DMA_CH4_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE |
                   DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
                   
        //
    // DMA CH5
    //
    DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(MTR1_PWM_V_BASE + EPWM_O_CMPA),
                        dma_epwm_config.dmaConfigsCycleV);
    DMA_configBurst(DMA_CH5_BASE, 2, 1, 1); //4 bursts --> One for for each up and down of the center aligned PWM
    DMA_configTransfer(DMA_CH5_BASE, 1, 1, -2); //4 Transfers, CMPAHR  ,   CMPA   ,   CMPBHR  ,   CMPB
    DMA_configMode(DMA_CH5_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE |
                   DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); //Every channel triggers on the 1SOCA or same trigger
                  
        //
    // DMA CH6
    //
    DMA_configAddresses(DMA_CH6_BASE, (uint16_t *)(MTR1_PWM_W_BASE + EPWM_O_CMPA),
                        dma_epwm_config.dmaConfigsCycleW);
    DMA_configBurst(DMA_CH6_BASE, 2, 1, 1); //4 bursts --> One for for each up and down of the center aligned PWM
    DMA_configTransfer(DMA_CH6_BASE, 1, 1, -2); //4 Transfers, CMPAHR  ,   CMPA   ,   CMPBHR  ,   CMPB
    DMA_configMode(DMA_CH6_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE |
                   DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
                   
    DMA_enableTrigger(DMA_CH6_BASE);

    //Start
    DMA_startChannel(DMA_CH4_BASE);
    DMA_startChannel(DMA_CH5_BASE);
    DMA_startChannel(DMA_CH6_BASE);

谢谢

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

    尊敬的 Hans:

    这些是 DMA 触发源。 如果您希望在 PWM 周期内生成两个 DMA 传输、您应该从 PWM 配置另一个 SOC 事件、并使用另一个 DMA 通道将此触发作为源。 当 TBCTR =CMPC 发生递减事件时、低字节片段可以从 PWM 生成 SOC_A。

    您可以生成另一个触发来针对 TBCTR =CMPC 递增事件生成 SOC_B。 然后、您将需要配置另一个 DMA 通道。

    //初始 ADC 触发-->用于 FOC
    ePWM_setADCTriggerSource (obj->pwmHandle[0]、ePWM_SOC_A、ePWM_SOC_TBCTR_D_CMPC);//ePWM_SOC_TBCTR_D_CMPC
    ePWM_enableADCTrigger (obj->pwmHandle[0]、ePWM_SOC_A);