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.

[参考译文] DRV8329AEVM:开发新电路板

Guru**** 657930 points
Other Parts Discussed in Thread: DRV8329, CSD19506KTT, UCC27284, DRV8329AEVM, C2000WARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/motor-drivers-group/motor-drivers/f/motor-drivers-forum/1268529/drv8329aevm-developing-new-board

器件型号:DRV8329AEVM
主题中讨论的其他器件:DRV8329CSD19506KTTUCC27284C2000WARE

大家好、

半桥栅极驱动器用3个 UCC27284替换了 DRV8329+CSD19506KTT 以控制 BLDC、可能需要您的帮助:

1) 1) 在 hal.c 中配置 PWM、EPWM3没有波形、而其他两个相位有 PWM 波形:

// GPIO227->EPWM3A->M1_UH
GPIO_setPinConfig (GPIO_227_EPWM3_A);
GPIO_setDirectionMode (227、GPIO_DIR_MODE_OUT);
GPIO_setPadConfig (227、GPIO_PIN_TYPE_STD);

// GPIO230->EPWM3B->M1_UL
GPIO_setPinConfig (GPIO_230_EPWM3_B);
GPIO_setDirectionMode (230、GPIO_DIR_MODE_OUT);
GPIO_setPadConfig (230、GPIO_PIN_TYPE_STD);

// GPIO0->EPWM1A->M1_VH
GPIO_setPinConfig (GPIO_0_EPWM1_A);
GPIO_setDirectionMode (0、GPIO_DIR_MODE_OUT);
GPIO_setPadConfig (0、GPIO_PIN_TYPE_STD);

// GPIO1->EPWM1B->M1_VL
GPIO_setPinConfig (GPIO_1_EPWM1_B);
GPIO_setDirectionMode (1、GPIO_DIR_MODE_OUT);
GPIO_setPadConfig (1、GPIO_PIN_TYPE_STD);


// GPIO2->EPWM2_A->M1_WH
GPIO_setPinConfig (GPIO_2_EPWM2_A);
GPIO_setDirectionMode (2、GPIO_DIR_MODE_OUT);
GPIO_setPadConfig (2、GPIO_PIN_TYPE_STD);

// GPIO3->EPWM2_B->M1_WL
GPIO_setPinConfig (GPIO_3_EPWM2_B);
GPIO_setDirectionMode (3、GPIO_DIR_MODE_OUT);
GPIO_setPadConfig (3、GPIO_PIN_TYPE_STD);

2) 请参阅具有非 SPI 接口的 UCC27284的 DRV8329AEVM 控制流程。 您能否帮助分享如何移植软件、以及是否有任何可用的参考文档? 该软件基于 c2000\c2000_SDK_4_02_01_00\solutions\universal_motorcontrol_lab\f280013x Ware_Motor 项目。

您能帮助检查这个问题吗? 谢谢。

此致、

切里

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

    嘿 Cherry、

    我将在下周了解并提供反馈。

    此致!
    阿克沙伊

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

    嘿 Cherry、

    似乎这个问题更多地与 C2000Ware 有关、因此我将让他们评论。

    此致!
    阿克沙伊

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

    尊敬的  Akshay:

    感谢您和 C2000团队的支持、期待您的更新。

    谢谢。此致、

    切里

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

    您好!

    对延迟回复深表歉意。

    首先、您在使用什么 C2000器件-它是 F280013x 吗?

    其次、用于 ePWM3与 ePWM1和2的 ePWM 配置代码是否有差异? 如果这基于通用电机控制实验、还请检查是否使用了 ePWM6而不是 ePWM3 -几种不同的 C2000/逆变器器件组合就是这种情况。

    第三、如果您想了解通用电机控制实验室代码的移植、UMCL 用户指南中有一个部分讨论了如何移植到其他 C2000 MCU 和逆变器板。 您还在寻找什么?

    此致、
    杰森·奥斯博尔恩

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

    尊敬的  Jason Osborn:

    感谢您的答复。

    目前有三组 PWM 波形、但 PWM 波形中的死区配置不起作用。 PWM 波使用 ePWM1、ePWM2和 ePWM3。 代码还确认 DB 已配置、请查看以下代码:  

    void HAL_setupPWMs(HAL_MTR_Handle handle)
    {
    
    HAL_MTR_Obj *obj = (HAL_MTR_Obj *)handle;
    uint16_t cnt;
    
    uint16_t pwmPeriodCycles = (uint16_t)(USER_M1_PWM_TBPRD_NUM);
    uint16_t numPWMTicksPerISRTick = USER_M1_NUM_PWM_TICKS_PER_ISR_TICK;
    
    // disable the ePWM module time base clock sync signal
    // to synchronize all of the PWMs
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
    // turns off the outputs of the EPWM peripherals which will put the power
    // switches into a high impedance state.
    EPWM_forceTripZoneEvent(obj->pwmHandle[0], EPWM_TZ_FORCE_EVENT_OST);
    EPWM_forceTripZoneEvent(obj->pwmHandle[1], EPWM_TZ_FORCE_EVENT_OST);
    EPWM_forceTripZoneEvent(obj->pwmHandle[2], EPWM_TZ_FORCE_EVENT_OST);
    
    for(cnt=0; cnt<3; cnt++)
    {
    // 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_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_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_LOW,
    EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    
    EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
    EPWM_AQ_OUTPUT_A,
    EPWM_AQ_OUTPUT_LOW,
    EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
    EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
    EPWM_AQ_OUTPUT_A,
    EPWM_AQ_OUTPUT_HIGH,
    EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    
    // 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);
    
    #endif //!MOTOR1_ISBLDC
    
    // 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_enableInterrupt(obj->pwmHandle[0]);
    
    EPWM_setADCTriggerSource(obj->pwmHandle[0],
    EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
    
    // ADC SOC trigger for the 1st dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[1],
    EPWM_SOC_A,
    EPWM_SOC_TBCTR_U_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_A);
    
    // ADC SOC trigger for the 2nd dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[1],
    EPWM_SOC_B,
    EPWM_SOC_TBCTR_U_CMPD);
    
    EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_B);
    
    // ADC SOC trigger for the 3rd dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[2],
    EPWM_SOC_A,
    EPWM_SOC_TBCTR_D_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_A);
    
    // ADC SOC trigger for the 4th dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[2],
    EPWM_SOC_B,
    EPWM_SOC_TBCTR_D_CMPD);
    
    EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_B);
    #else //!(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
    // setup the Event Trigger Selection Register (ETSEL)
    EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
    
    EPWM_enableInterrupt(obj->pwmHandle[0]);
    
    EPWM_setADCTriggerSource(obj->pwmHandle[0],
    EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
    #endif // !(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
    
    // setup the Event Trigger Prescale Register (ETPS)
    if(numPWMTicksPerISRTick > 15)
    {
    numPWMTicksPerISRTick = 15;
    }
    else if(numPWMTicksPerISRTick < 1)
    {
    numPWMTicksPerISRTick = 1;
    }
    
    EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMTicksPerISRTick);
    
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A,
    numPWMTicksPerISRTick);
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B,
    numPWMTicksPerISRTick);
    
    #if defined(MOTOR1_DCLINKSS)
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_A,
    numPWMTicksPerISRTick);
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_B,
    numPWMTicksPerISRTick);
    
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_A,
    numPWMTicksPerISRTick);
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_B,
    numPWMTicksPerISRTick);
    #endif //MOTOR1_DCLINKSS
    
    // 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);
    
    // write the PWM data value for ADC trigger
    #if defined(MOTOR1_DCLINKSS)
    EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_A);
    EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_B);
    
    EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_A);
    EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_B);
    
    EPWM_setCounterCompareValue(obj->pwmHandle[1],
    EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1);
    EPWM_setCounterCompareValue(obj->pwmHandle[1],
    EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
    
    EPWM_setCounterCompareValue(obj->pwmHandle[2],
    EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1);
    EPWM_setCounterCompareValue(obj->pwmHandle[2],
    EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
    
    #endif //MOTOR1_DCLINKSS
    
    
    return;
    
    } 

    谢谢。此致、

    切里

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

    樱桃、

    当您说 PWM 中的死区配置不起作用时、这到底是什么意思? 您在示波器中看到的哪种行为指示 DB 子模块未正确配置?

    此外,您发送的代码有4个大括号{和3个右大括号},因此不太可能正确编译-同样由于这个原因,我无法分辨 for 循环的结尾在哪里。

    此致、
    杰森·奥斯博尔恩

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

    尊敬的 Jason  Osborn:

    当您说 PWM 中的死区配置不起作用时,这到底是什么意思? 您在示波器中看到了哪些行为、表明 DB 子模块未正确配置?

    该问题是由于 DB 模块配置的死区太小、并且示波器上的扩展波形不明显造成的。 很明显、客户正在尝试增加死区时间。

    现在、PWM 波形控制 BLDC 有另一个问题:

    每组 PWM 波都需要与死区配置互补、以防止同一组 MOS 同时导通导致短路。 根据通用电机控制项目和实验用户指南、三组 PWM 波的相位需要错位。 但没有介绍如何为三组波形配置相位差、导致客户侧三组 PWM 波的高相位完全相同、 并且 MOS 管运行异常、导致输入电源频繁波动。

    您能帮助分享如何配置驱动三相 BLDC 的 PWM 波的相位吗?

    以下是 TI 开发板的 PWM 设置的完整函数、其中宏定义使用 MOTOR1_DCLINKSS:  

    void HAL_setupPWMs(HAL_MTR_Handle handle)
    {
    HAL_MTR_Obj *obj = (HAL_MTR_Obj *)handle;
    uint16_t cnt;
    
    uint16_t pwmPeriodCycles = (uint16_t)(USER_M1_PWM_TBPRD_NUM);
    uint16_t numPWMTicksPerISRTick = USER_M1_NUM_PWM_TICKS_PER_ISR_TICK;
    
    // disable the ePWM module time base clock sync signal
    // to synchronize all of the PWMs
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
    // turns off the outputs of the EPWM peripherals which will put the power
    // switches into a high impedance state.
    EPWM_forceTripZoneEvent(obj->pwmHandle[0], EPWM_TZ_FORCE_EVENT_OST);
    EPWM_forceTripZoneEvent(obj->pwmHandle[1], EPWM_TZ_FORCE_EVENT_OST);
    EPWM_forceTripZoneEvent(obj->pwmHandle[2], EPWM_TZ_FORCE_EVENT_OST);
    
    #if defined(BSXL8323RS_REVA) || defined(BSXL8323RH_REVB) || \
    defined(BSXL8353RS_REVA) || defined(BSXL8316RT_REVA) || \
    defined(BSXL3PHGAN_REVA) || defined(HVMTRPFC_REV1P1) || \
    defined(DRV8329AEVM_REVA)
    
    for(cnt=0; cnt<3; cnt++)
    {
    // 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_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_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);
    
    #if defined(MOTOR1_ISBLDC)
    // 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_LOW,
    EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    
    // setup the Action-qualifier Continuous Software Force Register (AQCSFRC)
    EPWM_setActionQualifierContSWForceAction(obj->pwmHandle[cnt],
    EPWM_AQ_OUTPUT_B,
    EPWM_AQ_SW_OUTPUT_LOW);
    
    // setup the Dead-Band Generator Control Register (DBCTL)
    EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, false);
    EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, false);
    
    #else //!MOTOR1_ISBLDC
    
    
    #if defined(MOTOR1_DCLINKSS)
    // 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_LOW,
    EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    
    EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
    EPWM_AQ_OUTPUT_A,
    EPWM_AQ_OUTPUT_LOW,
    EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
    EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
    EPWM_AQ_OUTPUT_A,
    EPWM_AQ_OUTPUT_HIGH,
    EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    #else // !(MOTOR1_DCLINKSS)
    // 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);
    
    #endif // !(MOTOR1_DCLINKSS)
    
    // 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);
    
    #endif //!MOTOR1_ISBLDC
    
    // 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);
    }
    
    // BSXL8323RS_REVA || BSXL8323RH_REVB || BSXL8353RS_REVA || \
    // BSXL8316RT_REVA || BSXL3PHGAN_REVA || HVMTRPFC_REV1P1 || \
    // DRV8329AEVM_REVA
    #else
    #error The PWM is not configured for motor_1 control
    #endif // boards
    
    #if defined(MOTOR1_ISBLDC)
    // setup the Event Trigger Selection Register (ETSEL)
    EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
    
    EPWM_disableInterrupt(obj->pwmHandle[0]);
    
    EPWM_setADCTriggerSource(obj->pwmHandle[0],
    EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO);
    
    EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
    
    EPWM_setADCTriggerSource(obj->pwmHandle[0],
    EPWM_SOC_B, EPWM_SOC_TBCTR_U_CMPB);
    
    EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_B);
    #elif defined(MOTOR1_DCLINKSS)
    // setup the Event Trigger Selection Register (ETSEL)
    EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
    
    EPWM_enableInterrupt(obj->pwmHandle[0]);
    
    EPWM_setADCTriggerSource(obj->pwmHandle[0],
    EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
    
    // ADC SOC trigger for the 1st dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[1],
    EPWM_SOC_A,
    EPWM_SOC_TBCTR_U_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_A);
    
    // ADC SOC trigger for the 2nd dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[1],
    EPWM_SOC_B,
    EPWM_SOC_TBCTR_U_CMPD);
    
    EPWM_enableADCTrigger(obj->pwmHandle[1], EPWM_SOC_B);
    
    // ADC SOC trigger for the 3rd dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[2],
    EPWM_SOC_A,
    EPWM_SOC_TBCTR_D_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_A);
    
    // ADC SOC trigger for the 4th dc-link current sampling
    EPWM_setADCTriggerSource(obj->pwmHandle[2],
    EPWM_SOC_B,
    EPWM_SOC_TBCTR_D_CMPD);
    
    EPWM_enableADCTrigger(obj->pwmHandle[2], EPWM_SOC_B);
    #else //!(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
    // setup the Event Trigger Selection Register (ETSEL)
    EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
    
    EPWM_enableInterrupt(obj->pwmHandle[0]);
    
    EPWM_setADCTriggerSource(obj->pwmHandle[0],
    EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
    
    EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
    #endif // !(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
    
    // setup the Event Trigger Prescale Register (ETPS)
    if(numPWMTicksPerISRTick > 15)
    {
    numPWMTicksPerISRTick = 15;
    }
    else if(numPWMTicksPerISRTick < 1)
    {
    numPWMTicksPerISRTick = 1;
    }
    
    EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMTicksPerISRTick);
    
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A,
    numPWMTicksPerISRTick);
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B,
    numPWMTicksPerISRTick);
    
    #if defined(MOTOR1_DCLINKSS)
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_A,
    numPWMTicksPerISRTick);
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[1], EPWM_SOC_B,
    numPWMTicksPerISRTick);
    
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_A,
    numPWMTicksPerISRTick);
    EPWM_setADCTriggerEventPrescale(obj->pwmHandle[2], EPWM_SOC_B,
    numPWMTicksPerISRTick);
    #endif //MOTOR1_DCLINKSS
    
    // 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);
    
    // write the PWM data value for ADC trigger
    #if defined(MOTOR1_DCLINKSS)
    EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_A);
    EPWM_clearADCTriggerFlag(obj->pwmHandle[1], EPWM_SOC_B);
    
    EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_A);
    EPWM_clearADCTriggerFlag(obj->pwmHandle[2], EPWM_SOC_B);
    
    EPWM_setCounterCompareValue(obj->pwmHandle[1],
    EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1);
    EPWM_setCounterCompareValue(obj->pwmHandle[1],
    EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
    
    EPWM_setCounterCompareValue(obj->pwmHandle[2],
    EPWM_COUNTER_COMPARE_C, pwmPeriodCycles>>1);
    EPWM_setCounterCompareValue(obj->pwmHandle[2],
    EPWM_COUNTER_COMPARE_D, pwmPeriodCycles>>1);
    
    #endif //MOTOR1_DCLINKSS
    return;
    
    }

    谢谢。此致、

    切里

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

    您好 Cherry:

    • 要查找  单个 ePWM 高侧和低侧之间的死区(在 ePWM 时钟节拍 MTR1_PWM_DBRED_CNT MTR1_PWM_DBFED_CNT中)、请在hal.h文件中搜索和。 默认值通常没有问题、但如果更改了这些值、请确保它们彼此相等。

    • 对于三相输出、我认为我明白混淆的地方。 通用实验室中的三组 PWM 波形及类似波形在该过程中的任何点都不会手动偏移。 相反、由于电机的三相由于电机的性质而相互偏移、来自 ADC 的测量值将反映这一点。 对于三个不同的 ADC 值、SVGEN_run() 空间矢量调制例程和 HAL_writePWMData() PWM CMPx 计算函数将始终导致三个 EPWM 之间的 CMPx 值存在明显差异。

      如果计算出的三个电流相位彼此同相、请检查 ADC 采样硬件和软件或用于单分流器重建例程的参数。 这里似乎有些地方可能出错了。 您能否从示波器发送波形图像?

    此致、
    杰森·奥斯博尔恩

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

    尊敬的  Jason Osborn:

    客户遵循 TI 的开发文档并将系统构建级别设置为 DMC_BUILDLEVEL = 1、该阶段只是检测 MCU PWM 波形输出和 ADC 采样、而不是采样后波形计算。  他们希望确保 3组 PWM 在该阶段的正常波形是什么样的。 它们的 PWM 波现在可通过死区确认:

    谢谢。此致、

    切里

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

    您好 Cherry:

    我很高兴听到数据库已被确认。

    在构建级别1中、根据 通用电机控制实验室用户指南时、PWM 波形没有偏移。

    听起来一切看起来都应该是一样的。 如果以后有任何问题、敬请告知!

    此致、
    杰森·奥斯博尔恩

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

    尊敬的  Jason Osborn:

    感谢您的帮助、客户已查看您提供的文档、 此问题应与软件 ADC 或硬件的配置有关。 客户对 ADC 配置有一些疑问、您能帮助进行研究吗?

    1) 1) 关于 ADC_BASE、如果对引脚选择 A4进行多路复用、 是否需要 配置 ADCA_BASE? 如果引脚选择 C14进行了多路复用、 是否需要配置 ADCC_BASE? 这两个选项是否是任意配置的?  

    #define MTR1_VU_ADC_BASE ADCA_BASE   // ADCA-A6*
    #define MTR1_VV_ADC_BASE ADCA_BASE   // ADCC-A3*/C5
    #define MTR1_VW_ADC_BASE ADCA_BASE   // ADCA-A2*/C9
    #define MTR1_VDC_ADC_BASE ADCA_BASE  // ADCA-A15*/C7
    #define MTR1_POT_ADC_BASE ADCC_BASE  // ADCC-C6*

    2) 2)调整 ADC_NUMBER、您能否帮助详细说明如何配置每个通道的 SOC 编号?  为什么 ADCA-A6* 被配置为 ADC_SOC_Number1、而 ADCA-A15*/C7 被配置为 ADC_SOC_Number4?

    #define MTR1_VU_ADC_SOC_NUM ADC_SOC_SOC_number1   // ADCA-A6*-SOC1
    #define MTR1_VV_ADC_SOC_NUM ADC_SOC_SOC_number2   // ADCC-A3*/C5 -SOC2
    #define MTR1_VW_ADC_SOC_NUM ADC_SOC_SOC_Number3   // ADCA-A2*/C9 -SOC3
    #define MTR1_VDC_ADC_SOC_NUM ADC_SOC_SOC_Number4  // ADCA-A15*/C7 -SOC4
    #define MTR1_POT_ADC_SOC_NUM ADC_SOC_Number4  // ADCC-C6*-SOC4

    3) 3)关于中断配置、为什么 MTR1_ADC_INT_base 配置为 ADCA_BASE?  它是否与 ADC 对其进行采样的引脚有关? 为什么 MTR1_ADC_INT_NUM 被配置为 number1? 为什么将 MTR1_ADC_INT_SOC 配置为 ADC_SOC_Number4?  

    //中断
    #define MTR1_PWM_INT_BASE MTR1_PWM_U_BASE   // EPWM1

    #define MTR1_ADC_INT_BASE ADCA_BASE   // ADCA-A15 -SOC4
    #define MTR1_ADC_INT_NUM    ADC_INT_NUMBER1 // ADCA_INT1-SOC4
    #define MTR1_ADC_INT_SOC    ADC_SOC_Number4 // ADCA_INT1-SOC4

    4) 4)关于  IDC、您能否帮助详细说明什么是 IDC 功能以及需要配置它?  

    #define MTR1_IDC1_TRIGGER_SOC  ADC_TRIGGER_EPWM2_SOCA // EPWM2_SOCA
    #define MTR1_IDC2_TRIGGER_SOC  ADC_TRIGGER_EPWM2_SOCB // EPWM2_SOCB
    #define MTR1_IDC3_TRIGGER_SOC  ADC_TRIGGER_EPWM6_SOCA // EPWM6_SOCA
    #define MTR1_IDC4_TRIGGER_SOC  ADC_TRIGGER_EPWM6_SOCB // EPWM6_SOCB
    #endif //!FAST_DCLINKSS

    #define MTR1_IDC1_ADC_BASE ADCC_BASE  // ADCC-A11/C0*
    #define MTR1_IDC2_ADC_BASE ADCC_BASE  // ADCC-A11/C0*
    #define MTR1_IDC3_ADC_BASE ADCC_BASE  // ADCC-A11/C0*
    #define MTR1_IDC4_ADC_BASE ADCC_BASE  // ADCC-A11/C0*

    #define MTR1_IDC1_ADCRES_BASE ADCCRESULT_BASE  // ADCC-A11/C0*
    #define MTR1_IDC2_ADCRES_BASE ADCCRESULT_BASE  // ADCC-A11/C0*
    #define MTR1_IDC3_ADCRES_BASE ADCCRESULT_BASE  // ADCC-A11/C0*
    #define MTR1_IDC4_ADCRES_BASE ADCCRESULT_BASE  // ADCC-A11/C0*

    定制电路板配置 ADC 后、在构建级别1中进行调试时无法刷写 motorVars_M1.ISRCount、但可以刷新使用开发包之前的配置。  

    谢谢。此致、

    切里

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

    您好!

    浏览您的问题、其中大多数与 ADC 外设基本原理有关。 我建议客户通读 C2000 Academy 第4章。 模拟子系统、第1节、模数转换器(ADC)-并不是每个问题都得到了解答,但它是一个很好的基准知识来处理 ADC 问题。 此外、 F280013x TRM ADC 章节 非常有用的资源。

    对于这些具体问题:

    1. 关于 ADC_BASE、如果对引脚选择 A4进行多路复用、 是否需要 配置 ADCA_BASE? 如果引脚选择 C14进行了多路复用、 是否需要配置 ADCC_BASE? 这两个选项是否是任意配置的?

      1. 本质上、F280013x MCU 有2个不同的 ADC 外设- ADCA 和 ADCC。 每个外设都可以访问不同的引脚集。 要执行模数转换、您使用的 ADC 外设必须进行正确配置。

        这意味着如果您想转换引脚 A6上的模拟信号、您需要使用 ADCA。 如果您要转换 C5上的模拟信号、则需要使用 ADCC。 两个 ADC 外设确实共用几个引脚(例如引脚 A7/C3)、从而允许它们转换相同的输入信号、但是它们是不同的外设。

    2. 对 ADC_NUMBER 重新分级后、您能否帮助详细说明如何配置每个通道的 SOC 编号?  为什么 ADCA-A6* 配置为 ADC_SOC_Number1,而 ADCA-A15*/C7 配置为 ADC_SOC_Number4。
      1. C2000 Academy ADC 部分非常好地回答了这个问题。 基本上、每个 ADC 可配置为进行多达16次转换。 为了便于使用、ADC 文档主要通过 SOC 启动转换来指代每次转换。 要转换引脚 A6、您需要在 ADCA 上设置1个 SOC、但您可以选择任一种。

        例如、假设我要转换引脚 A6、并且我已经任意决定使用 ADCA SOC12。 现在、我需要在 ADCA.ADCSOC12CTL 寄存器中设置正确的配置值。  ADCSOC12CTL[CHSEL]= 0x6、因为它是 ADCA 输入6、 ADCSOC12CTL[TRIGSEL]允许我决定该转换何时发生。

        对于通用电机控制实验、已在 half 文件中为您设置了所有适当的 driverlib 函数。 您所需要做的就是确保 正确设置预定义(如 MTR1_VU_ADC_SOC_NUM)。

        要将 MTR1 VU 设置为输入引脚 A6、通道 SOC12、您需要设置:

        #define MTR1_VU_ADC_BASE    ADCA_BASE // ADCA-A6* // Pin *A*6 requires ADC*A*
        #define MTR1_VU_ADC_SOC_NUM ADC_SOC_NUMBER12 // ADCA-A6* -SOC12 // In our example, we're arbitrarily setting SOC12
        #define MTR1_ADC_TRIGGER_SOC    ADC_TRIGGER_EPWM1_SOCA // EPWM1_SOCA // This configures ePWM1 SOCA as the trigger for all of motor 1's SOCs.



    3. 关于中断配置、为什么 MTR1_ADC_INT_base 配置为 ADCA_BASE?  它是否与 ADC 对其进行采样的引脚有关? 为什么 MTR1_ADC_INT_NUM 被配置为 number1? 为什么将 MTR1_ADC_INT_SOC 配置为 ADC_SOC_Number4?
      1. 对于 ADC、中断通常在任意选择的 SOC 完成转换时触发。 我们想要 在电机1的一个 SOC 结束时触发 motor1CtrlISR ()。
        1. MTR1_ADC_INT_BASE 必须与我们要用于触发的 SOC 相同的 ADC (ADCA 或 ADCC)。 如上所述、SOC 与特定 ADC 相关联、这意味着我们要使用的引脚通常决定我们必须使用什么基极。 在这种情况下、我们要使用由 ADCA SOC4转换的引脚 A15、因此我们选择 MTR1_ADC_INT_base 作为 ADCA_BASE。

        2. 每个 ADC 可以生成多达4个中断(ADCINT1至 ADCINT4)。 我们只需要1、因此我们只选择第一个开放时隙 ADCINT1。 这意味着我们选择 MTR1_ADC_INT_NUM 为 ADC_INT_NUMBER1。

        3. 我们基本上可以选择一个任意 SOC 来触发中断、  只要我们在开始中断前确信所有必要的转换已经结束。 一般来说、这意味着你要将中断设置为最低优先级的 SOC -尽管我需要仔细检查代码以确保正确无误、我可以确定这是通用实验室的功能、或者至少是非常相似的功能。 由于我们希望触发 SOC4、因此将 MTR1_ADC_INT_SOC 设置为 ADC_SOC_Number4 

    4. 关于  IDC,您能否帮助详细说明什么是 IDC 功能以及需要配置它?
      1. MTR1_IDCx 是通用电机控制实验室使用的惯例、用来指用于转换单分流器硬件的通道。 您将在代码中注意到每个 IDC SOC 都指向同一引脚、但由不同的事物触发。 这只是意味着我们要在几个不同的时间点测量同一个引脚。 要了解其配置方式、请 在 hal.c 文件中搜索 motor1_DCLINKSS。 在这些#if defined (motor1_DCLINKSS)部分中、您可以找到与单分流器硬件相关的特定配置。

    如果客户还有其他有关 ADC 的问题、尤其是如果问题与 ADC 相关的术语相关、我强烈建议您通读 TRM 一章。

    我希望这对您有所帮助!
    杰森·奥斯博尔恩