如何利用EK-TM4C123GXL获取DC电源的稳定ADC读数?
TM4C123GXL ADC读取DC电压波动问题排查与咨询
项目背景
使用Texas Instruments EK-TM4C123GXL LaunchPad开展项目,测量面包板电源模块(hw-131)的电压,采用板载ADC模块读取时出现明显波动。
问题详情
- 将电源模块3.3V端子连接至TM4C123GXL的ADC输入引脚PE3/AIN0;
- ADC转换采用内部3.3V参考电压;
- 经万用表确认,输入至TM4C123GXL的电压稳定在2.8V,波动不超过±0.05V;
- 测试发现,即使输入电压稳定,ADC输出值仍波动明显,且电源模块关闭时波动更显著。
已尝试措施
- 检查ADC配置与时钟设置,确保采样时间和分辨率合理;
- 实现8样本平均,但未完全消除波动。
相关代码
#include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_ints.h" #include "driverlib/sysctl.h" #include "driverlib/adc.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "driverlib/pin_map.h" #define NUM_SAMPLES 8 // Function to configure UART0 for communication void ConfigureUART(void) { // Enable UART0 and GPIOA peripherals SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // Configure PA0 and PA1 as UART pins GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // Initialize UART0 with a baud rate of 115200 UARTStdioConfig(0, 115200, SysCtlClockGet()); } // ADC0 interrupt handler void ADC0IntHandler(void) { // Clear the ADC interrupt flag ADCIntClear(ADC0_BASE, 0); uint32_t ui32ADC0Value[NUM_SAMPLES]; uint32_t ui32Sum = 0; uint32_t i = 0; // Get the ADC sequence data ADCSequenceDataGet(ADC0_BASE, 0, ui32ADC0Value); // Sum the ADC values while(i < NUM_SAMPLES){ ui32Sum += ui32ADC0Value[i]; i++; } // Calculate the average ADC value uint32_t ui32Average = ui32Sum / NUM_SAMPLES; // Print the average ADC value to the UART UARTprintf("ADC Average Value: %d\n", ui32Average); // Calculate the input voltage in volts (assuming 3.3V reference voltage) float voltage = (ui32Average * 3.3) / 4096.0; uint32_t v_int_part = voltage; // Integer part of the voltage uint32_t v_frac_part = (voltage - v_int_part) * 1000; // Fractional part in millivolts // Print the calculated voltage to the UART UARTprintf("Input Voltage: %d.%03d V\n", v_int_part, v_frac_part); } int main(void) { // Set the system clock to 50MHz (200MHz PLL / 4) SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // Configure UART for debugging ConfigureUART(); // Enable the ADC0 and GPIOE peripherals SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // Wait for the peripherals to be ready while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0) || !SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)) { } // Configure PE3 as ADC input GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); // Set the ADC clock source and rate ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 8); // Configure ADC sequence 0 to be triggered by the processor ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0); // Configure all 8 steps in the sequence to sample from CH0 (PE3) ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); // Enable interrupt on last step // Enable ADC sequence 0 ADCSequenceEnable(ADC0_BASE, 0); // Clear any pending ADC interrupts ADCIntClear(ADC0_BASE, 0); // Enable ADC interrupts ADCIntEnable(ADC0_BASE, 0); // Enable the ADC0 sequence 0 interrupt in the NVIC IntEnable(INT_ADC0SS0); // Set ADC0 sequence 0 interrupt priority to highest (0) IntPrioritySet(INT_ADC0SS0, 0x00); while(1) { // Trigger the ADC conversion ADCProcessorTrigger(ADC0_BASE, 0); // Delay to simulate some processing time SysCtlDelay(SysCtlClockGet() / 6); } }
电路示意图

波动数据
- 电源模块开启时:

- 电源模块关闭时:

咨询问题
- 是否有更优软件方法稳定ADC读数?
- 是否需要特定ADC配置来稳定输入信号?
- DC电压测量应用有哪些最佳实践?
内容的提问来源于stack exchange,提问作者陳軍翰
相关产品推荐
相关产品推荐

