You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用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);
    }
}

电路示意图

my circuit

波动数据

  • 电源模块开启时:when the power supply module ON
  • 电源模块关闭时:when the power supply module OFF

咨询问题

  • 是否有更优软件方法稳定ADC读数?
  • 是否需要特定ADC配置来稳定输入信号?
  • DC电压测量应用有哪些最佳实践?

内容的提问来源于stack exchange,提问作者陳軍翰

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:34:51