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_Ex5_SoC_Continuous、该示例将2个连续转换为1个转换。
代码如下:
// // Included Files // #include "driverlib.h" #include "device.h" // // Function Prototypes // void configureADC(uint32_t adcBase); void setupADCContinuous(uint32_t adcBase, uint32_t channel); // // Defines // #define RESULTS_BUFFER_SIZE 1024 //buffer for storing conversion results //(size must be multiple of 16) #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]; uint16_t resultsIndex; 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 the ADC and power it up // configureADC(ADCA_BASE); // // Setup the ADC for continuous conversions on channel 0 // setupADCContinuous(ADCA_BASE, 0U); // // Initialize results buffer // for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++) { adcAResults[resultsIndex] = 0; } resultsIndex = 0; // // Enable global Interrupts and higher priority real-time debug events: // EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM // // Take conversions indefinitely in loop // do { // // Enable ADC interrupts // ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1); // ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER2); // ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER3); // ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER4); // // Clear all interrupts flags(INT1-4) // HWREGH(ADCA_BASE + ADC_O_INTFLGCLR) = 0x000F; // // Initialize results index // resultsIndex = 0; // // Software force start SOC0 to SOC7 // // HWREGH(ADCA_BASE + ADC_O_SOCFRC1) = 0x00FF; ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER1 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER2 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER3 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER4 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER5 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER6 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER7 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER8 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER9 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER10 ); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER11); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER12); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER13); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER14); ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER15); // // Keep taking samples until the results buffer is full // while(resultsIndex < RESULTS_BUFFER_SIZE) { // // Wait for first set of 8 conversions to complete // while(false == ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1)); // // Clear the interrupt flag // ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1); // // Save results for first 8 conversions // // Note that during this time, the second 8 conversions have // already been triggered by EOC6->ADCIN1 and will be actively // converting while first 8 results are being saved // adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER1); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER2); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER3); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER4); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER5); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER6); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER7); // // Wait for the second set of 8 conversions to complete // // while(false == ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER4)); // // Clear the interrupt flag // // ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER4); // // Save results for second 8 conversions // // Note that during this time, the first 8 conversions have // already been triggered by EOC14->ADCIN2 and will be actively // converting while second 8 results are being saved // adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER8); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER9); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER10); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER11); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER12); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER13); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER14); adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER15); } // // Disable all ADCINT flags to stop sampling // ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER1); // ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER2); // ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER3); // ADC_disableInterrupt(ADCA_BASE, ADC_INT_NUMBER4); // // At this point, adcAResults[] contains a sequence of conversions // from the selected channel // // // Software breakpoint, hit run again to get updated conversions // asm(" ESTOP0"); } while(1); // Loop forever } // // configureADC - Write ADC configurations and power up the ADC for both // ADC A and ADC B // void configureADC(uint32_t adcBase) { // // Set ADCDLK divider to /4 // ADC_setPrescaler(adcBase, ADC_CLK_DIV_4_0); // // Set resolution and signal mode (see #defines above) and load // corresponding trims. // #if(EX_ADC_RESOLUTION == 12) ADC_setMode(adcBase, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED); #elif(EX_ADC_RESOLUTION == 16) ADC_setMode(adcBase, ADC_RESOLUTION_16BIT, ADC_MODE_DIFFERENTIAL); #endif // // Set pulse positions to late // ADC_setInterruptPulseMode(adcBase, ADC_PULSE_END_OF_CONV); // // Power up the ADCs and then delay for 1 ms // ADC_enableConverter(adcBase); // // Delay for 1ms to allow ADC time to power up // DEVICE_DELAY_US(1000); } // // setupADCContinuous - setup the ADC to continuously convert on one channel // void setupADCContinuous(uint32_t adcBase, uint32_t channel) { uint16_t acqps; // // Determine acquisition window (in SYSCLKS) based on resolution // if(EX_ADC_RESOLUTION == 12) { acqps = 30; // 150ns } else //resolution is 16-bit { acqps = 64; // 320ns } // // - 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. // - NOTE: A slightly longer S+H window is used with 12-bit resolution to // ensure the data collection loop can keep up with the ADC // // // Configure SOCs channel no. & acquisition window. // ADC_setupSOC(adcBase, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER1, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER2, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER3, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER4, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER5, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER6, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER7, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER8, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER9, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER10, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER11, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER12, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER13, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER14, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); ADC_setupSOC(adcBase, ADC_SOC_NUMBER15, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps); // // Setup interrupt trigger for SOCs. ADCINT2 will trigger first 8 SOCs. // ADCINT1 will trigger next 8 SOCs // // // ADCINT2 trigger for SOC0-SOC7 // ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER0, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER1, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER2, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER3, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER4, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER5, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER6, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER7, ADC_INT_SOC_TRIGGER_ADCINT1); // // ADCINT1 trigger for SOC8-SOC15 // ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER8, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER9, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER10, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER11, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER12, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER13, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER14, ADC_INT_SOC_TRIGGER_ADCINT1); ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER15, ADC_INT_SOC_TRIGGER_ADCINT1); // // Disable Interrupt flags // ADC_disableInterrupt(adcBase, ADC_INT_NUMBER1); // ADC_disableInterrupt(adcBase, ADC_INT_NUMBER2); // ADC_disableInterrupt(adcBase, ADC_INT_NUMBER3); // ADC_disableInterrupt(adcBase, ADC_INT_NUMBER4); // // Enable continuous mode // ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER1); // ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER2); // ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER3); // ADC_enableContinuousMode(adcBase, ADC_INT_NUMBER4); // // Configure interrupt triggers // ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER15); // ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER14); // ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER13); // good results // ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER5); } // // End of file //
当我输入5kHz 正弦波并使用不同的中断源时、我看到有干扰。 我希望 ADC_setInterruptSource (adcBase、ADC_INT_number1、ADC_SOC_NUMBER15); 不应出现任何干扰、因为它会确保所有转换完成。 这是图形的屏幕截图
谢谢 Vadim
您好!
由于假期,专家不在办公室。 请在星期二之前回复。
谢谢。
您好 Vadim、
如果所有16个 SOC 只使用1个中断、则在开始转换下一组 SOC 之前、没有足够的时间转换这些值。 您查看的示例提供了触发所有16个 SOC (至少2个中断)的正确方法、这样就有足够的时间在读取其他 SOC 的结果的同时转换 SOC。
此外、作为后续说明、请使用 Instert -> Code 方法复制和粘贴代码。 您在此处插入代码的方式会使读取变得不必要、我将无法轻松找到您所谈论的内容。
此致、
Omer Amir
您好、Omer、
感谢您的支持。 我知道 ADC SOC 根据轮循方法具有优先级。 我理解这一点、因为在前一个转换未完成之前、当前转换将不会开始。
在这种情况下、分配给最后一个 SOC15的中断应触发第一个通道的第一个 SOC0? 因此,如果我的 ePWM 时基大于连续16 SOC*75 ns,我应该看不到任何干扰?
我认为我所做的与示例相同、A2输入的示例中具有16个连续通道与4个通道之间存在差异。
//! This example sets up ePWM1 to periodically trigger a set of conversions on //! ADCA including multiple SOCs that all convert A2 to achieve oversampling on //! A2. //! //! ADCA Interrupt ISRs are used to read results of ADCA. //! //! \b External \b Connections \n //! - A0, A1, A2 should be connected to signals to be converted. //! //! \b Watch \b Variables \n //! - \b adcAResult0 - Digital representation of the voltage on pin A0 //! - \b adcAResult1 - Digital representation of the voltage on pin A1 //! - \b adcAResult2 - Digital representation of the voltage on pin A2 //!
谢谢 Vadim
PS 我尝试按照您的建议输入代码。
您好 Vadim、
[引用 userid="301556" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1187303/tms320f28377d-tms320f28377d/4481943 #4481943"]在这种情况下、分配给最后一个 SOC15的中断应触发第一个通道的第一个 SOC0?分配给 SOC 的中断将导致 SOC 触发、因此您可以使用1个中断来触发多个 SOC。 但是、代码的结构是这样的、这样中断1会触发全部16个 SOC。 当到达 ISR 或再次触发中断时、数据可能已就绪、也可能未就绪、SOC 可能没有时间在触发另一个中断之前转换结果(您可以监控中断溢出状态)。
[引用 userid="301556" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1187303/tms320f28377d-tms320f28377d/4481943 #4481943"]因此,如果我的 EPWM 时基大于连续16 SOC*75 ns,我不应该看到任何干扰?如果您使用 ePWM 来触发 SOC、而不仅仅是中断或软件触发器、那么如果您使时基周期足够长、那就可以了。 但是、您拥有的代码看起来不像 ePWM 被用来触发 SOC、它看起来就像您正在使用 ADC 中断1。
[引用 userid="301556" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1187303/tms320f28377d-tms320f28377d/4481943 #4481943"]我尝试按照您的建议输入代码[/quot]我已重新编排了您的原始帖子、以便更易于查看。
此致、
Omer Amir
谢谢 Omer、
因此 、如果我在中使用 ADC_TRIGGER_SW_ONLY
ADC_setupSOC(adcBase, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY, (ADC_Channel)channel, acqps);
我必须定义触发 SOC ADC_INT_SOC_TRIGGER_ADCINT1的中断
ADC_setInterruptSOCTrigger(adcBase, ADC_SOC_NUMBER0, ADC_INT_SOC_TRIGGER_ADCINT1);
在原始示例中、16个 SOC 被分成2组、每个组由不同的中断触发。
谢谢 Vadim
您好 Vadim、
感谢 Omer 的快速响应!
Vadim