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.

[参考译文] TMS320F28069M:ADC 中的同步采样模式

Guru**** 2558600 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1188401/tms320f28069m-simultaneous-sampling-mode-in-adc

器件型号:TMS320F28069M

我对 ADC 中的同步采样模式有以下疑问:

1、是否有任何示例可供我参考、用于使用 ADC 的同步采样模式

2.在用户指南的第8.6节:同步采样模式下,将:

通常、在应用中、只会使用对的偶数 SOCx。 但是、这是可能的
以改用奇数 SOCx、甚至同时使用两者。 在后一种情况下、两个 SOCx 触发器都将启动转换。
因此、我们强烈建议谨慎操作、因为两个 SOCx 的结果都将存储到同一个 ADCRESULTx 寄存器中、可能的话
相互覆盖。

我想同时使用偶数和奇数 SOCx。 我想了解如何避免覆盖 ADCRESULTx 寄存器中的数据。

用户指南链接: www.ti.com/.../spruh18i.pdf

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

    Hi Dev、

    遗憾的是、没有现有的示例可用于同步、但我已对 Adsome wiex-example 进行了快速修改、以回答您的第二个问题。 在此消息的底部、我包含了一个新的.c 文件、您可以使用它来替换 Adexc 示例中的2806xAdc.c 文件。  

    使用新文件、我启用了 SOC0和 SOC1的同步采样、两者都由来自 ePWM 的相同信号触发。 SOC0对 ADCINA2/ADCINB2进行采样、而 SOC1对 ADCINA4/ADCINB4进行采样。 当任一 SOC 完成 ADCINA 转换时、结果存储在 ADCRESULT0中、而 ADCINB 转换存储在 ADCRESULT1中。

    我已经设置了一个名为 ADC_ISR 的 ADC 中断、该中断由 EOC1信号触发。 使用 INTPULSEPOS 寄存器、EOC1设置为在 ADCRESULT1锁存并准备就绪时触发 ADC_ISR、这始终在 ADCRESULT0准备就绪后触发。 数据表中的图8-27和下面的屏幕截图显示了该时序。  

    ADC_ISR 仅从 ADCRESULT0获取结果、并将其放入称为 Voltage1的数组中、然后将 ADCRESULT1放入 Voltage2中。 由于 SOC0和 SOC1将始终同时触发、因此每个"电压"阵列中的结果在 SOC0和 SOC1之间交替变化。 在我的示例中、我将采样引脚从 SOC0接地、同时将 SOC1连接到3.3V。 这使得数组中的值在高电平(~4000)和低电平(~0)之间交替、如下所示。  

    在我的示例中、我已使用跳线连接:

    ADCINA2 => GPIO14 (低电平)  

    ADCINB2 => GPIO15 (低电平)

    ADCINA4 => GPIO11 (高电平)

    ADCINB4 => GPIO12 (高电平)

    只要您将 ADC 输入连接到正确的高电压和低电压、您就应该在 Voltage1和 Voltage2数组中看到交替值。 这显示了 ADC_ISR 在 ADCRESULT 寄存器被覆盖之前将 ADC 结果保存在存储器的其他位置。  

    此致、
    Ben Collier

    //###########################################################################
    //
    // FILE:   Example_2806xAdcSoc.c
    //
    // TITLE:  ADC Start of Conversion Example
    //
    //! \addtogroup f2806x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //! 
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC - ADCINT1.
    //! Two channels are converted, ADCINA4 and ADCINA2.
    //! 
    //! \b Watch \b Variables \n
    //! - Voltage1[10]    - Last 10 ADCRESULT0 values
    //! - Voltage2[10]    - Last 10 ADCRESULT1 values
    //! - ConversionCount - Current result number 0-9
    //! - LoopCount       - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright:
    // Copyright (C) 2009-2022 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 "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    
    //
    // Function Prototypes
    //
    __interrupt void adc_isr(void);
    void Adc_Config(void);
    
    //
    // Globals
    //
    Uint16 LoopCount;
    Uint16 ConversionCount;
    Uint16 Voltage1[100];
    Uint16 Voltage2[100];
    
    //
    // Main
    // 
    void main(void)
    {
        //
        // Step 1. Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        // This example function is found in the F2806x_SysCtrl.c file.
        //
        InitSysCtrl();
    
        //
        // Step 2. Initialize GPIO:
        // This example function is found in the F2806x_Gpio.c file and
        // illustrates how to set the GPIO to it's default state.
        //
        // InitGpio();  // Skipped for this example
    
        //
        // Step 3. Clear all interrupts and initialize PIE vector table:
        // Disable CPU interrupts
        //
        DINT;
    
        //
        // Initialize the PIE control registers to their default state.
        // The default state is all PIE interrupts disabled and flags
        // are cleared.
        // This function is found in the F2806x_PieCtrl.c file.
        //
        InitPieCtrl();
    
        //
        // Disable CPU interrupts and clear all CPU interrupt flags:
        //
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        // The shell ISR routines are found in F2806x_DefaultIsr.c.
        // This function is found in F2806x_PieVect.c.
        //
        InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        EALLOW;  // This is needed to write to EALLOW protected register
        PieVectTable.ADCINT1 = &adc_isr;
        EDIS;    // This is needed to disable write to EALLOW protected registers
    
        //
        // Step 4. Initialize all the Device Peripherals:
        // This function is found in F2806x_InitPeripherals.c
        // InitPeripherals(); // Not required for this example
        //
        InitAdc();  // For this example, init the ADC
        AdcOffsetSelfCal();
    
        //
        // Step 5. User specific code, enable interrupts:
        //
    
        //
        // Enable ADCINT1 in PIE
        //
        PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
        IER |= M_INT1; 					   // Enable CPU Interrupt 1
        EINT;          					   // Enable Global interrupt INTM
        ERTM;          					   // Enable Global realtime interrupt DBGM
    
        LoopCount = 0;
        ConversionCount = 0;
    
        //
        // Configure ADC
        //
        EALLOW;
    
        //
        // Enable an GPIO output on GPIO14 and GPIO15, set it high
        //
        GpioCtrlRegs.GPAPUD.bit.GPIO14 = 1;   // Enable pullup on GPIO14
        GpioDataRegs.GPASET.bit.GPIO14 = 0;   // Load output latch
        GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 0;  // GPIO14 = GPIO14
        GpioCtrlRegs.GPADIR.bit.GPIO14 = 1;   // GPIO14 = output
    
        GpioCtrlRegs.GPAPUD.bit.GPIO15 = 1;   // Enable pullup on GPIO15
        GpioDataRegs.GPASET.bit.GPIO15 = 0;   // Load output latch
        GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 0;  // GPIO15 = GPIO15
        GpioCtrlRegs.GPADIR.bit.GPIO15 = 1;   // GPIO15 = output
    
        GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;   // Enable pullup on GPIO11
        GpioDataRegs.GPASET.bit.GPIO11 = 1;   // Load output latch
        GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 0;  // GPIO11 = GPIO11
        GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;   // GPIO11 = output
    
        GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;   // Enable pullup on GPIO12
        GpioDataRegs.GPASET.bit.GPIO12 = 1;   // Load output latch
        GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;  // GPIO12 = GPIO12
        GpioCtrlRegs.GPADIR.bit.GPIO12 = 1;   // GPIO12 = output
    
        //
        // Enable Simultaneous Sampling
        //
        AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 1;
    
        //
        // Set SOC0 and SOC1 to high priority
        //
        //AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 2;
    
    
    
        AdcRegs.ADCCTL2.bit.ADCNONOVERLAP = 1; // Enable non-overlap mode
        
        //
        // ADCINT1 trips after AdcResults latch, called "Late Interrupt Pulse" in datasheet / TRM
        //
        AdcRegs.ADCCTL1.bit.INTPULSEPOS	= 1;
        
        AdcRegs.INTSEL1N2.bit.INT1E     = 1;  // Enabled ADCINT1
        AdcRegs.INTSEL1N2.bit.INT1CONT  = 0;  // Disable ADCINT1 Continuous mode
        
        //
        // setup EOC1 to trigger ADCINT1 to fire
        //
        AdcRegs.INTSEL1N2.bit.INT1SEL 	= 1;
        
        AdcRegs.ADCSOC0CTL.bit.CHSEL 	= 2;  // set SOC0 channel select to ADCINA2
        AdcRegs.ADCSOC1CTL.bit.CHSEL 	= 4;  // set SOC1 channel select to ADCINA4
        
        //
        // set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts
        // first then SOC1
        //
        AdcRegs.ADCSOC0CTL.bit.TRIGSEL 	= 5;
        
        //
        // set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts 
        // first then SOC1
        //
        AdcRegs.ADCSOC1CTL.bit.TRIGSEL 	= 5;
        
        //
        // set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
        //
        AdcRegs.ADCSOC0CTL.bit.ACQPS 	= 6;
        
        //
        // set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
        //    
        AdcRegs.ADCSOC1CTL.bit.ACQPS 	= 6;
        EDIS;
    
        //
        // Assumes ePWM1 clock is already enabled in InitSysCtrl();
        //
        EPwm1Regs.ETSEL.bit.SOCAEN	= 1;		// Enable SOC on A group
        EPwm1Regs.ETSEL.bit.SOCASEL	= 4;		// Select SOC from CMPA on upcount
        EPwm1Regs.ETPS.bit.SOCAPRD 	= 1;		// Generate pulse on 1st event
        EPwm1Regs.CMPA.half.CMPA 	= 0x0080;	// Set compare A value
        EPwm1Regs.TBPRD 			= 0xFFFF;	// Set period for ePWM1
        EPwm1Regs.TBCTL.bit.CTRMODE	= 0;		// count up and start
    
        //
        // Wait for ADC interrupt
        //
        for(;;)
        {
            LoopCount++;
        }
    }
    
    //
    // adc_isr - 
    //
    __interrupt void
    adc_isr(void)
    {
        Voltage1[ConversionCount] = AdcResult.ADCRESULT0;
        Voltage2[ConversionCount] = AdcResult.ADCRESULT1;
        
        //
        // If 20 conversions have been logged, start over
        //
        if(ConversionCount == 99)
        {
            ConversionCount = 0;
        }
        else
        {
            ConversionCount++;
        }
    
        //
        // Clear ADCINT1 flag reinitialize for next SOC
        //
        AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
        
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
    
        return;
    }
    
    //
    // End of File
    //
    
    

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

    您好!

    更简单的一点是:如果 ADC ISR 运行时间太长、则 ADC 将有时间覆盖结果寄存器、然后 CPU 才能获取该值。 在这种情况下、ADCRESULTx 寄存器将被覆盖。 在我发布的示例中、ISR 必须在少于20个 ADCCLK 周期的时间内执行。 如果 ISR 太长、您可以减慢 ADCCLK 速度或执行其他操作来减慢 ADC 转换速度。  

    此致、

    Ben Collier

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

    您好

    关于同步采样模式、我还有一个问题。 以下是我尝试获取的配置:

    1、所有16个 ADC 通道用于 ADC 转换

    2.我正在使用偶数 SOCx 对

    3、所有 SOCx 三倍频源均相同、设为5 (ePWM1.ADCSOCA)

    4.我已将 SOCPRIORITY 设置为15,因此所有 SOC 都具有高优先级

    5.我已将 INTSEL1N2.bit.IN1SEL 设置为15,我知道 EOC15将是最后一次发生,它应该会触发我的 ADCINT1。 在 ISR 内部、我正在读取所有 ADCRESULT 寄存器

    6、EPWM CMPA 设为0x1000、TBPRD 设为0x1010。

    问题是我的 ADC 寄存器在 ADCINA3和 ADCINB3前报告正确的值。 文章、说明 ADCRESULT 寄存器正在提供垃圾数据。

    您能不能向我建议我的配置有误

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

    Hi Dev、

    请分享您正在使用的代码吗? 如果您愿意、您可以脱机以私人邮件形式发送它。 可能  有多种设置会导致这种情况、因此我希望确保所有设置都正确。

    此致、

    Ben Collier

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

    您好

    我在这里附上了我的文件。 请您建议我们在这里交流一下。 因此可以避免时区差异。

    e2e.ti.com/.../main.cpp

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

    Hi Dev、

    我将尝试调试您明天早上发布的示例。 您是否尝试运行我在之前的响应中发送的示例代码? 如果是、您是否能够使用该代码对通道 A4进行正确采样?  

    我主要在美国中部时间上午8点至下午6点(芝加哥/达拉斯时间)提供、因此请期待届时的回复。  

    此致、

    Ben Collier

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

    Hi Dev、

    我重复了您的问题、但我并不完全确定原因。 我会联系一些语言来了解他们的想法。  

    此致、

    Ben Collier

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

    Hi Dev、

    很抱歉、我们花了很长时间才回复您。 我仍在努力寻找这个问题的原因、我在本周五与更多 ADC 专家举行了另一次会议。 当我们找到解决方案时、我会告诉您。

    此致、

    Ben Collier

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

    Hi Dev、

    是否可以尝试在 SOC 14而非15末尾触发中断? 如果这不起作用、我可以发送我编辑过的示例、该示例成功地使用相同的触发器触发和采样所有 SOC。

    此致、

    Ben Collier

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

    您好 Benjamin、

    EOC14帮助解决了该问题。 我想了解为什么 EOC15不起作用。

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

    Hi Dev、

    我将深入了解这一点、并在明天返回给您。 我对我的答复拖延表示歉意。

    此致、

    Ben Collier

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

    Hi Dev、

    令人遗憾的是,我一直被其他项目所困住,我也没有能够深入研究这一点。 我问过的同事也无法作出快速反应。 请告诉我这是否是一个关键问题。

    此致、

    Ben Collier

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

    您好 Benjamin、

    没问题。 我们可以在将来对此进行讨论。 如果我们将 EOC14保持为 ADCINT 的中断源、则根据最新更新。 一切都按预期正常工作。