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.

[参考译文] TMS320F28379D:如何确认 PWM 是否触发 SOC 中断?

Guru**** 2540720 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1346289/tms320f28379d-how-to-confirm-that-pwm-is-triggering-soc-interrupt

器件型号:TMS320F28379D
主题中讨论的其他器件:C2000WARE

我正在将 F28335 DSP 的程序转换为 F28379D DSP。 我当前关注的是由 PWM 驱动的 ADC。 我已将 ADC 通道修改为使用组 A-D、并认为 ADC 读取和转换逻辑正确。 我已对组 ADCA 和 ADCC 进行编程、以便将 PWM1中的 SOCA 用于 SOC 触发器、并将 ADCB 和 ADCD 用于使用 PWM1中的 SOCB。  

EOC 正在发生并触发 EOC ISR 的执行。 但当我检查采集的 ADC 数据时、无论 ADC 通道的输入信号的幅度如何、所有结果似乎都只是显示了一个非零但非常低的 ADC 计数。

那么、我的问题是:我是否有方法可以确认 SOC 事件已发生且正在获取数据? 是否有可能 SOC 事件未发生而 EOC 中断仍然发生? 否则、是否还有无法获取 ADC 输入数据的其他可能原因? "我知道,有很多人。"  您是否有一个包含 F28379D DSP 目标上 ADC 调试提示的出版物?

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

    大家好、Thomas:

    我建议首先尝试使用 C2000Ware 中的其中一个 ADC 示例、以确保其在您的器件上正常工作、然后通过比较两组代码来调试您自己的程序。 ADC 示例可以在 C2000Ware_5_01_00_00\driverlib\f2837xd\examples\cpu1\adc 中找到。

    除此之外、如果您得到的 ADC 结果不正确 、则验证基准是否正确、与 ADC 引脚的连接是否稳定(您还应验证所施加的电压是否有效)、测量预期结果与观察到的结果之间的差异(是否一致)、 验证 ADC 是否正确启用(即遵循示例代码)、并使用软件触发器测量已知的直流电压。 这些只是一些需要检查的项目、很遗憾、您的问题不是很具体、因此还没有任何针对性的调试问题需要咨询。

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

    Omer -在发表文章后、我意识到应该按照您的建议执行-将我的 ADC 逻辑与 C2000ware 示例进行比较。 示例项目 adc_soc_pwm_cpu01最接近我们正在使用的方法。 我当前有一个原型板、具有对 ADCB 通道5的可靠输入、可用于测试目的、因此、我创建了示例源的修改版本、并将新源文件命名为 adcb_soc_pwm_cpu01.c。 我制作了示例 C 源代码和我修改的 C 源代码的本地副本、以便可以在编译中包含或排除其中一个、从而测试其中一个或另一个的性能。  

    项目现在处于访问 ADCA 引脚0的示例版本运行的状态、并用零填充结果缓冲区。 ADCB 引脚5版本在读取循环期间停止、结果索引始终不会超过0。 我已经附上了该项目的 ZIP 文件。  你能否让我知道我错了什么,使 SOC 或 EOC 事件似乎不会发生?

     e2e.ti.com/.../adc_5F00_soc_5F00_software_5F00_cpu01.zip

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

    大家好、Thomas:

    ADCB 引脚5版本在读取循环期间停止,结果索引永远不会上升到0以上。

    我无法导入您的代码、因为出现了一些错误、但我在 driverlib 示例 adc_ex2_soc_epwm 中进行了验证、当我将 ADCA_BASE 设置为 ADCB_BASE、将 ADCIN0设置 为 ADCIN5并更改中断以使用 ADCB 而非 ADCA 时、代码执行正常:

    //#############################################################################
    //
    // FILE:   adc_ex2_soc_epwm.c
    //
    // TITLE:  ADC ePWM Triggering
    //
    //! \addtogroup driver_example_list
    //! <h1>ADC ePWM Triggering</h1>
    //!
    //! This example sets up ePWM1 to periodically trigger a conversion on ADCA.
    //!
    //! \b External \b Connections \n
    //!  - A0 should be connected to a signal to convert
    //!
    //! \b Watch \b Variables \n
    //! - \b adcAResults - A sequence of analog-to-digital conversion samples from
    //!   pin A0. The time between samples is determined based on the period
    //!   of the ePWM timer.
    //!
    //
    //#############################################################################
    //
    // 
    // $Copyright:
    // Copyright (C) 2013-2024 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //#############################################################################
    //
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    
    //
    // Defines
    //
    #define RESULTS_BUFFER_SIZE     256
    #define EX_ADC_RESOLUTION       12
    // 12 for 12-bit conversion resolution, which supports (ADC_MODE_SINGLE_ENDED)
    // Sample on single pin (VREFLO is the low reference)
    // Or 16 for 16-bit conversion resolution, which supports (ADC_MODE_DIFFERENTIAL)
    // Sample on pair of pins (difference between pins is converted, subject to
    // common mode voltage requirements; see the device data manual)
    
    //
    // Globals
    //
    uint16_t adcAResults[RESULTS_BUFFER_SIZE];   // Buffer for results
    uint16_t index;                              // Index into result buffer
    volatile uint16_t bufferFull;                // Flag to indicate buffer is full
    
    //
    // Function Prototypes
    //
    void initADC(void);
    void initEPWM(void);
    void initADCSOC(void);
    __interrupt void adcA1ISR(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();
    
        //
        // Interrupts that are used in this example are re-mapped to ISR functions
        // found within this file.
        //
        Interrupt_register(INT_ADCB1, &adcA1ISR);
    
        //
        // Set up the ADC and the ePWM and initialize the SOC
        //
        initADC();
        initEPWM();
        initADCSOC();
    
        //
        // Initialize results buffer
        //
        for(index = 0; index < RESULTS_BUFFER_SIZE; index++)
        {
            adcAResults[index] = 0;
        }
    
        index = 0;
        bufferFull = 0;
    
        //
        // Enable ADC interrupt
        //
        Interrupt_enable(INT_ADCB1);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // Loop indefinitely
        //
        while(1)
        {
            //
            // Start ePWM1, enabling SOCA and putting the counter in up-count mode
            //
            EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
            EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    
            //
            // Wait while ePWM1 causes ADC conversions which then cause interrupts.
            // When the results buffer is filled, the bufferFull flag will be set.
            //
            while(bufferFull == 0)
            {
            }
            bufferFull = 0;     // Clear the buffer full flag
    
            //
            // Stop ePWM1, disabling SOCA and freezing the counter
            //
            EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
            EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
    
            //
            // Software breakpoint. At this point, conversion results are stored in
            // adcAResults.
            //
            // Hit run again to get updated conversions.
            //
            ESTOP0;
        }
    }
    
    //
    // Function to configure and power up ADCA.
    //
    void initADC(void)
    {
        
        //
        // Set ADCDLK divider to /4
        //
        ADC_setPrescaler(ADCB_BASE, ADC_CLK_DIV_4_0);
    
        //
        // Set resolution and signal mode (see #defines above) and load
        // corresponding trims.
        //
    #if(EX_ADC_RESOLUTION == 12)
        ADC_setMode(ADCB_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
    #elif(EX_ADC_RESOLUTION == 16)
        ADC_setMode(ADCB_BASE, ADC_RESOLUTION_16BIT, ADC_MODE_DIFFERENTIAL);
    #endif
    
        //
        // Set pulse positions to late
        //
        ADC_setInterruptPulseMode(ADCB_BASE, ADC_PULSE_END_OF_CONV);
    
        //
        // Power up the ADC and then delay for 1 ms
        //
        ADC_enableConverter(ADCB_BASE);
        DEVICE_DELAY_US(1000);
    }
    
    //
    // Function to configure ePWM1 to generate the SOC.
    //
    void initEPWM(void)
    {
        //
        // Disable SOCA
        //
        EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
    
        //
        // Configure the SOC to occur on the first up-count event
        //
        EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
        EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1);
    
        //
        // Set the compare A value to 1000 and the period to 1999
        // Assuming ePWM clock is 100MHz, this would give 50kHz sampling
        // 50MHz ePWM clock would give 25kHz sampling, etc. 
        // The sample rate can also be modulated by changing the ePWM period
        // directly (ensure that the compare A value is less than the period). 
        //
        EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 1000);
        EPWM_setTimeBasePeriod(EPWM1_BASE, 1999);
    
        //
        // Set the local ePWM module clock divider to /1
        //
        EPWM_setClockPrescaler(EPWM1_BASE,
                               EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        //
        // Freeze the counter
        //
        EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
    }
    
    //
    // Function to configure ADCA's SOC0 to be triggered by ePWM1.
    //
    void initADCSOC(void)
    {
        //
        // Configure SOC0 of ADCA to convert pin A0. The EPWM1SOCA signal will be
        // the trigger.
        // - For 12-bit resolution, a sampling window of 15 (75 ns at a 200MHz
        //   SYSCLK rate) will be used.  For 16-bit resolution, a sampling window
        //   of 64 (320 ns at a 200MHz SYSCLK rate) will be used.
        // - NOTE: A longer sampling window will be required if the ADC driving
        //   source is less than ideal (an ideal source would be a high bandwidth
        //   op-amp with a small series resistance). See TI application report
        //   SPRACT6 for guidance on ADC driver design.
        //
    
    #if(EX_ADC_RESOLUTION == 12)
        ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA,
                     ADC_CH_ADCIN5, 15);
    #elif(EX_ADC_RESOLUTION == 16)
        ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA,
                     ADC_CH_ADCIN5, 64);
    #endif
    
        //
        // Set SOC0 to set the interrupt 1 flag. Enable the interrupt and make
        // sure its flag is cleared.
        //
        ADC_setInterruptSource(ADCB_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);
        ADC_enableInterrupt(ADCB_BASE, ADC_INT_NUMBER1);
        ADC_clearInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1);
    }
    
    //
    // ADC A Interrupt 1 ISR
    //
    __interrupt void adcA1ISR(void)
    {
        //
        // Add the latest result to the buffer
        //
        adcAResults[index++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
    
        //
        // Set the bufferFull flag if the buffer is full
        //
        if(RESULTS_BUFFER_SIZE <= index)
        {
            index = 0;
            bufferFull = 1;
        }
    
        //
        // Clear the interrupt flag
        //
        ADC_clearInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1);
    
        //
        // Check if overflow has occurred
        //
        if(true == ADC_getInterruptOverflowStatus(ADCB_BASE, ADC_INT_NUMBER1))
        {
            ADC_clearInterruptOverflowStatus(ADCB_BASE, ADC_INT_NUMBER1);
            ADC_clearInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1);
        }
    
        //
        // Acknowledge the interrupt
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
    }
    

    我认为您缺少了正确配置 ADC B 中断的一些步骤(您引用的示例看起来好像是使用的是软件触发器、这可能就是您的项目中缺少一些代码的原因)。 请查看 driverlib 示例、以验证您是否执行了正确的步骤。 ADC 的中断启用有多个步骤(如在 Interrupt_enable 函数本身中所见)。

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

    Omer -在开始的句子中、您已运行 driverlib 示例 adc_ex2_soc_epwm、就好像我可以从 C2000ware 下载一个项目并运行它一样。 但是我在 C200ware 版本4.1的副本中找到的只是源文件、没有项目支持或指向依赖项的链接。 我尝试只是将源文件添加到我的 C2000ware 项目中、版本生成了一个包含7个无法找到的资源的列表。 您似乎有机会接触到我遗漏的资源或知识。 当我在主 C 文件之外找不到任何资源的时候、你也许能给我说明如何启动一个 driverlib 项目吗?

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

    大家好、Thomas:

    我不知道您正在使用的 C2000Ware 的哪个版本、因此我参考了 C2000Ware 5.01版。 我安装了版本4.01,发现此示例,存在、可导入和编译。 我不确定 您版本的 C2000Ware 是否收到了修改、或者它是其他一些 SDK 的一部分、该 SDK 可能未包含所有正确的文件、 但是、如果您执行 C2000Ware 的新安装(4.01或最新) 、则会提供和使用示例 adc_ex2_soc_ePWM (我今天已经验证了)。

    shiwei Nie 说:
    如果我找不到除主 C 文件之外的任何资源,您能否给我有关如何启动 driverlib 项目的说明?

    您是否完全能够导入任何 driverlib 项目? 我找不到从 bitfield 迁移到 driverlib 的资源、但一般来说、driverlib 在工程属性中使用以下配置:

    最简单的方法是导入 driverlib 工程并确保设置一致、但考虑到这似乎不可能、您可能必须验证上述选项。 如果仍然无法正常工作、请告诉我。

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

    Omer -感谢您验证我的 C2000ware 副本是否应该具有可导入的项目。 我一直在使用一台客户端提供的笔记本电脑来处理此项目、这台笔记本电脑具有非常强大的安全工具、因此可能已经将 driverlib 项目隔离为危险项目。 我将尝试使用一个版本5.01.1的新副本。

    如果 C2000ware 安装的某些部分被隔离、非常感谢您指导如何创建项目。 当我有一个正在运行的 driverlib 项目时、我会回复您。   

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

    我已经安装了 C2000ware 5.02、并对照 C2000ware 4.01的内容进行了检查。 4.01中缺少一些项目、但缺少的文件看起来不重要。 因此,Windows 安全似乎不是缺少项目文件的原因。 从 v4.01导入 adc_ex2_soc_pwm 工程时、我无法在工程导入窗口中看到 CPU 文件夹中的任何.projectspec 文件。 不过我仍然选择了 CPU 文件夹、但确实显示了要导入的完整项目列表。

    我创建了一个并行源文件 adcB5_ex2_soc_pwm.c 来读取 ADCB5。  我同时运行了 A0和 B5版本。 在这两种情况下、adcResults 缓冲区读取所有256个数据样本的4095次计数。 成功! 感谢你的帮助。 我会将此方法应用于我的客户的软件