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.
我对 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
您好 Benjamin 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
您好 Benjamin Collier、
我在这里附上了我的文件。 请您建议我们在这里交流一下。 因此可以避免时区差异。
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 的中断源、则根据最新更新。 一切都按预期正常工作。