工具与软件:
您好!
我需要能够使用 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);
谢谢
