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.

[参考译文] TMS320F28386D:ECAP 模块的单次触发模式配置

Guru**** 2457760 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1424883/tms320f28386d-one-shot-mode-configuration-for-ecap-module

器件型号:TMS320F28386D

工具与软件:

您好!

我将尝试从数据表中执行以下示例:

我完成了所有配置的不同之处在于我做了:

下降沿上的 CAP1

上升沿上的 CAP2

下降沿上的 CAP3

上升沿上的 CAP4

此外、我将中断设置为仅在 CAP4就绪时才触发。

然后在中断中、CAP2、CAP3、CAP4的值与预期一致、但 CAP1在第一个中断中的值并不完全相同、它离开了1000个计数、并且对于每个中断、它都在预期值附近保持去抖、所有其他 CAPS 始终是正确的。

下面是我所做配置的 sudo 代码:

1 -禁用 SYNC (也冻结到 PWM 的时钟)
2-清除 AQ 子模块先前的配置
配置 ePWM 模块
3.1-设置 clk 预分频器
3.2 -设置时基周期
3.3设置时基计数模式
3.4-设置相移
3.5- SetActionQualifierAction
4 -启用 SYNC 和时钟到 PWM
设置中断功能
6 - 禁用并清除所有的捕捉标志和中断
 禁用 CAP1-CAP4寄存器加载和停止计数器
8- 在事件4时启用捕捉模式并停止捕捉
9 -将事件的极性设置为下降(CAP1)、上升(CAP2)、下降(CAP3)、上升(CAP4)边沿
10 - 为所有电容器将捕捉设置为时间差模式
11- 启用模块
11.1-启用加载计数器
11.2- setSyncOutMode
11.3- startCounter
11.4- EnableTimeStampCapture
11.5-启用 CAP4的中断
11.6 -启用模块中断
11.7-启用全局中断
12-请重新布设
等待中断并检查捕捉的值
14 -执行步骤13多路复用时间
每个中断的所有值都是正确的、CAP1除外。
有什么建议或原因吗?
注意:我使用的是单次触发模式、在中断内部、我在最后做的是:
1-清除中断
2-清除全局中断
重新布设
4- ClearAckGroup4.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Esmail:

    在执行单次触发模式时、请参阅有关 CAP1测量的此主题:

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/768599/tms320f28027-ecap-capture-example-cannot-capture-correct-period

    我希望这能解答您的问题。

    此致、

    Ryan Ma

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

    Ryan、您好!

    我检查了线程,但这没有解释,当我试图重置计数器,然后直接重新 ARM。 我仍然无法获得确切的值。

    不存在 ISR 执行时间问题。

    此致、

    Esmail

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

    尊敬的 Esmail:

    即使在单次触发模式下、TSCTR 也会持续运行。 在每个事件上、TSCTR 将继续复位。 处于单次触发模式并达到 STOP_Wrap 值时、CAP1-4寄存器在下一次 RE ARM 之前不会再加载。

    由于您在捕获事件4之后重新布防、因此 TSCTR 已经在连续计数、即使您将其复位、该值也将继续运行。 然后、如果您恰好在下降沿发生后对其进行 ARM、则会错过该事件、直到下一个下降沿将偏离 CAP1计数。  

    我建议使用 CAP2-4作为正确的值、就像在我们的软件示例中我们仅使用 CAP2-4作为有效测量一样。

    此致!

    Ryan Ma

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

    您好、Ryan、

    那么、如果我要执行以下操作:

    1-配置。

    2启动

    3-获得 ISR (此处的 CAP1值将会出错、但没关系)

    4 -在 ISR 结束时、我做了:

    4.1-通过置位 ECCTL2 寄存器的 CTRFILTRESET 位进行计数器复位。

    4.2-请重新布防。

    然后、在下一个 ISR 中、该值应该是正确的。

    此外、是否有任何可以完成的配置可以让我看到 CAP1正确值?

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

    尊敬的 Esmail:

    即使采用上述配置、在复位计数器时、计数器仍将连续运行。  

    尝试以下操作:

    1-配置。

    2启动

    3-获得 ISR (此处的 CAP1值将会出错、但没关系)

    4 -在 ISR 结束时、我做了:

    设置 TSCTRSTOP = 0

    4.1-通过置位 ECCTL2 寄存器的 CTRFILTRESET 位进行计数器复位。

    4.2-请重新布防。

    设置 TSCTRSTOP = 1

    另一个选项是将 eCAP 配置为连续运行。 这将具有正确的 CAP1值、因为 CAP 寄存器将根据事件连续加载。

    此致!

    Ryan Ma

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

    Ryan、您好、我尝试了第一个解决方案、但它不起作用。 第二个并非首选方法、因为我们要使用单次触发模式。

    另外、我需要注意的是、此问题仅发生在 EPWM15上、但对于 EPWM10和 EPWM9、我们没有看到该问题。

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

    您好、Ryan、如果 CAP1无法在单次触发模式下使用。 我无法在勘误表中找到该问题。 是否有用于定义此问题的勘误表?

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

    尊敬的 Esmail:

    让我与另一位同事讨论这个问题。 CAP1实际上取决于使用单次触发模式时何时重新布防。  

    此致!

    Ryan Ma

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

    您好、Ryan、

    是否有任何更新?

    此致!

    Esmail

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

    尊敬的 Esmail:

    我发现能得到 最接近结果的配置只能在 CAP2、CAP3和 CAP4事件后复位、此时 CAP1和 CAP2以单次触发模式运行、且时间差与 CAP3和 CAP4相同。

    您可以通过执行 CAP2 - CAP1值来获取脉冲宽度。 根据重新布防的发生时间、CAP1将会发生变化。  

    这对您有用吗?

    此致!

    Ryan Ma

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

    Ryan、您好!

    感谢您的答复。 您在此提出的建议、因为我知道在捕获了每个 CAP (CAP2、CAP3和 CAP4)后、我需要重新布防/重置所有 CAPS?

    -如果是这样,那么这不满足我正在尝试实施的测试案例,这是执行上述序列。

    此外、我不关注脉冲宽度、而是将所有电容器设置为相同值。

    此处的问题是、CAP1不会像其余电容那样冻结值、这个问题只会出现在 EPWM15中、但对于 EPWM10和 EPWM9、我们不会看到这个问题、那么您对此有何看法?

    总之、最好能为我提供一个执行上述序列的测试用例、以便为 EPWM15和 CAP1值冻结。

    如果我们实际上不能冻结 CAP1值、那么我想数据表或勘误表中应该会提供清晰的说明。

    非常感谢。

    Esmail

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

    尊敬的 Esmail:

    我将对此进行更深入的探讨。 上个星期我出差时出现延迟、对此深表歉意。

    此致!

    Ryan Ma

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

    Ryan、您好!

    感谢您的重播。 我希望你有一个良好的经验与您的商务旅行. 我将等待您的分析。

    此致!

    Esmail

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

    不客气!

    此致!

    Ryan Ma

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

    尊敬的 Esmail:

    CAP1取决于从 CAP4到生成中断、然后到重新启用的时间、然后将记录下一个下降沿。 由于您是以单次触发模式运行、因此我要重申一点、每次捕获之间的时间取决于此时序、因此始终会发生这种情况。 当重新布防时、TSCTR 不会进行复位。

    我希望这可以澄清您看到的问题。

    我想问一下、让所有 CAP 寄存器保持相同值的预期用例是什么? 我无法肯定为什么 EPWM10/9您没有看到该问题、因为这应该无关紧要。  

    此致!

    Ryan Ma

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

    尊敬的 Esmail:

    您可以尝试的另一个实验是在启用捕获事件4的中断之前、您可以确保在捕获事件2发生后重新激活。  

    下面是一个我编辑过的示例、为 CAP1捕获正确的值。

    //#############################################################################
    //
    // FILE:    ecap_capture_pwm.c
    //
    // TITLE:   Capture ePWM3.
    //
    //! \addtogroup driver_example_list
    //! <h1>eCAP Capture PWM Example</h1>
    //!
    //! This example configures ePWM3A for:
    //! - Up count mode
    //! - Period starts at 500 and goes up to 8000
    //! - Toggle output on PRD
    //!
    //! eCAP1 is configured to capture the time between rising
    //! and falling edge of the ePWM3A output.
    //!
    //! \b External \b Connections \n
    //! - eCAP1 is on GPIO16
    //! - ePWM3A is on GPIO4
    //! - Connect GPIO4 to GPIO16.
    //!
    //! \b Watch \b Variables \n
    //! - \b ecap1PassCount - Successful captures.
    //! - \b ecap1IntCount - Interrupt counts.
    //
    //#############################################################################
    //
    //
    // $Copyright: $
    //#############################################################################
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    //
    // Defines
    //
    #define PWM3_TIMER_MIN     500U
    #define PWM3_TIMER_MAX     8000U
    #define EPWM_TIMER_UP      1U
    #define EPWM_TIMER_DOWN    0U
    
    //
    // Globals
    //
    uint32_t ecap1IntCount;
    uint32_t ecap1PassCount;
    uint32_t epwm3TimerDirection;
    volatile uint32_t cap1Count;
    volatile uint32_t cap2Count;
    volatile uint32_t cap3Count;
    volatile uint32_t cap4Count;
    volatile uint16_t epwm3PeriodCount;
    
    //
    // Function Prototypes
    //
    void error(void);
    void initECAP(void);
    void initEPWM(void);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Configure GPIO4/5 as ePWM3A/3B
        //
        GPIO_setPadConfig(4,GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_4_EPWM3_A);
        GPIO_setPadConfig(5,GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_5_EPWM3_B);
    
        //
        // Board initialization
        // Configure GPIO 16 as eCAP input
        // Enable interrupts required for this example
        //
        Board_init();
        
        //
        // Configure ePWM
        //
        initEPWM();
    
    
    
    
        //
        // Initialize counters:
        //
        cap2Count = 0U;
        cap3Count = 0U;
        cap4Count = 0U;
        ecap1IntCount = 0U;
        ecap1PassCount = 0U;
        epwm3PeriodCount = 0U;
    
        //
        // Enable Global Interrupt (INTM) and Real time interrupt (DBGM)
        //
        ECAP_clearInterrupt(myECAP0_BASE,
            (ECAP_ISR_SOURCE_CAPTURE_EVENT_1  |
            ECAP_ISR_SOURCE_CAPTURE_EVENT_2  |
            ECAP_ISR_SOURCE_CAPTURE_EVENT_3  |
            ECAP_ISR_SOURCE_CAPTURE_EVENT_4  |
            ECAP_ISR_SOURCE_COUNTER_OVERFLOW |
            ECAP_ISR_SOURCE_COUNTER_PERIOD   |
            ECAP_ISR_SOURCE_COUNTER_COMPARE));
        ECAP_resetCounters(myECAP0_BASE);
    
        ECAP_reArm(myECAP0_BASE);
    
        while(!(ECAP_getInterruptSource(myECAP0_BASE) & ECAP_ISR_SOURCE_CAPTURE_EVENT_2))
        {
        }
        ECAP_clearInterrupt(myECAP0_BASE,
            (ECAP_ISR_SOURCE_CAPTURE_EVENT_1  |
            ECAP_ISR_SOURCE_CAPTURE_EVENT_2  |
            ECAP_ISR_SOURCE_CAPTURE_EVENT_3  |
            ECAP_ISR_SOURCE_CAPTURE_EVENT_4  |
            ECAP_ISR_SOURCE_COUNTER_OVERFLOW |
            ECAP_ISR_SOURCE_COUNTER_PERIOD   |
            ECAP_ISR_SOURCE_COUNTER_COMPARE));
        ECAP_resetCounters(myECAP0_BASE);
        ECAP_reArm(myECAP0_BASE);
        ECAP_enableInterrupt(myECAP0_BASE,(ECAP_ISR_SOURCE_CAPTURE_EVENT_4));
    
        EINT;
        ERTM;
    
        //
        // Loop forever. Suspend or place breakpoints to observe the buffers.
        //
        for(;;)
        {
           NOP;
        }
    }
    
    //
    // initEPWM - Configure ePWM
    //
    void initEPWM()
    {
        //
        // Disable sync(Freeze clock to PWM as well)
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Configure ePWM
        //       Counter runs in up-count mode.
        //       Action qualifier will toggle output on period match
        //
        EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBasePeriod(EPWM3_BASE, PWM3_TIMER_MIN);
        EPWM_setPhaseShift(EPWM3_BASE, 0U);
        EPWM_setActionQualifierAction(EPWM3_BASE,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_TOGGLE,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
        EPWM_setClockPrescaler(EPWM3_BASE,
                               EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_2);
    
        epwm3TimerDirection = EPWM_TIMER_UP;
    
        //
        // Enable sync and clock to PWM
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    }
    
    //
    // myECAP0 ISR
    //
    __interrupt void INT_myECAP0_ISR(void)
    {
        //
        // Get the capture counts. Each capture should be 4x the ePWM count
        // because of the ePWM clock divider.
        //
    
        cap1Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_1);
        cap2Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_2);
        cap3Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_3);
        cap4Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_4);
    
        //
        // Compare the period value with the captured count
        //
        epwm3PeriodCount = EPWM_getTimeBasePeriod(EPWM3_BASE);
    
    //    if(cap2Count > ((epwm3PeriodCount *4) + 4) ||
    //       cap2Count < ((epwm3PeriodCount *4) - 4))
    //    {
    //        error();
    //    }
    //
    //    if(cap3Count > ((epwm3PeriodCount *4) + 4) ||
    //       cap3Count < ((epwm3PeriodCount *4) - 4))
    //    {
    //        error();
    //    }
    //
    //    if(cap4Count > ((epwm3PeriodCount *4) + 4) ||
    //       cap4Count < ((epwm3PeriodCount *4) - 4))
    //    {
    //        error();
    //    }
    
        ecap1IntCount++;
    
        //
        // Keep track of the ePWM direction and adjust period accordingly to
        // generate a variable frequency PWM.
        //
        if(epwm3TimerDirection == EPWM_TIMER_UP)
        {
            if(epwm3PeriodCount < PWM3_TIMER_MAX)
            {
               EPWM_setTimeBasePeriod(EPWM3_BASE, ++epwm3PeriodCount);
            }
            else
            {
               epwm3TimerDirection = EPWM_TIMER_DOWN;
               EPWM_setTimeBasePeriod(EPWM3_BASE, ++epwm3PeriodCount);
            }
        }
        else
        {
            if(epwm3PeriodCount > PWM3_TIMER_MIN)
            {
                EPWM_setTimeBasePeriod(EPWM3_BASE, --epwm3PeriodCount);
            }
            else
            {
               epwm3TimerDirection = EPWM_TIMER_UP;
               EPWM_setTimeBasePeriod(EPWM3_BASE, ++epwm3PeriodCount);
            }
        }
    
        //
        // Count correct captures
        //
        ecap1PassCount++;
    
        //
        // Clear interrupt flags for more interrupts.
        //
        ECAP_clearInterrupt(myECAP0_BASE,ECAP_ISR_SOURCE_CAPTURE_EVENT_4);
        ECAP_clearGlobalInterrupt(myECAP0_BASE);
    
        //
        // Start eCAP
        //
        ECAP_reArm(myECAP0_BASE);
    
        //
        // Acknowledge the group interrupt for more interrupts.
        //
        Interrupt_clearACKGroup(INT_myECAP0_INTERRUPT_ACK_GROUP);
    }
    
    //
    // error - Error function
    //
    void error()
    {
        ESTOP0;
    }
    

    const ecap             = scripting.addModule("/driverlib/ecap.js", {}, false);
    const ecap1            = ecap.addInstance();
    const gpio             = scripting.addModule("/driverlib/gpio.js", {}, false);
    const gpio1            = gpio.addInstance();
    const inputxbar        = scripting.addModule("/driverlib/inputxbar.js", {}, false);
    const inputxbar1       = inputxbar.addInstance();
    const inputxbar_input  = scripting.addModule("/driverlib/inputxbar_input.js");
    const inputxbar_input1 = inputxbar_input.addInstance();
    
    /**
     * Write custom configuration values to the imported modules.
     */
    ecap1.$name                   = "myECAP0";
    ecap1.captureMode             = "ECAP_ONE_SHOT_CAPTURE_MODE";
    ecap1.eventStop               = "ECAP_EVENT_4";
    ecap1.eventOnePolarity        = "ECAP_EVNT_FALLING_EDGE";
    ecap1.eventThreePolarity      = "ECAP_EVNT_FALLING_EDGE";
    ecap1.interruptSourceCapture  = ["ECAP_ISR_SOURCE_CAPTURE_EVENT_4"];
    ecap1.counterResetOnEvent     = ["ECAP_EVENT_1","ECAP_EVENT_2","ECAP_EVENT_3","ECAP_EVENT_4"];
    ecap1.enableLoadCounter       = true;
    ecap1.ecapInput               = "ECAP_INPUT_INPUTXBAR7";
    ecap1.registerInterrupts      = true;
    ecap1.reArm                   = false;
    ecap1.ecapInt.enableInterrupt = true;
    
    gpio1.$name           = "myGPIO0";
    gpio1.qualMode        = "GPIO_QUAL_ASYNC";
    gpio1.gpioPin.$assign = "GPIO16";
    
    inputxbar1.$name = "myINPUTXBAR0";
    
    inputxbar_input1.$name          = "myINPUTXBARINPUT0";
    inputxbar_input1.inputxbarInput = "XBAR_INPUT7";
    inputxbar_input1.inputxbarGpio  = "GPIO16";

    此致!

    Ryan Ma

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

    Ryan、您好!

    感谢您的快速回复。 当重新布防时 TSCTR 不会复位、这是正确的行为吗?

    如果没有、那是提到的。

    谢谢。

    Esmail。

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

    对于用例、我仅在单次触发模式下测试 CAP1、2、3和4值。

    我会尝试您建议的配置、我会告诉您。

    谢谢。

    Esmail

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

    这是正确的行为。 我要归档 JIRA、以确保我们在 TRM 中更清楚地表明重新定位后 TSCTR 不会复位。

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1005226/launchxl-f280049c-ecap-once-capture-event-4-occurs-and-tscctr-resets-can-tscctr-reset-on-capture-event-1-if-rearm-has-not-occurred-in-the-isr

    此致!

    Ryan Ma