STM32 ADC 采集实战|电压采集、分压计算、数据滤波

摘要

ADC 是嵌入式项目最常用的模拟采集外设,很多人调试时会遇到采样跳变、读数不准、分压算错的问题。本文基于气体监测工控项目实战,讲解 STM32 单通道 ADC 采集原理、电阻分压计算、硬件降噪、软件滤波方案,附带精简可移植代码,同时梳理现场调试踩坑点,适合快速落地模拟量采集。

适用主控:STM32F103RCT6

一、项目场景

项目中采集外部 0~3.3V 模拟电压信号;外部传感器输出最高 5V,不能直接接入 STM32 的 ADC 引脚,需要电阻分压电路降压。采集原始 ADC 值存在小幅噪声,需要软件滤波稳定输出电压,用于后续数据上传、阈值判断。

二、硬件分压原理与计算

STM32F103 ADC 参考电压VREF = 3.3V,12 位 ADC,分辨率:

(ADC_{max}=4095)

(V_{in} = \frac{ADC_val}{4095} \times V_{REF})

外部输入 5V 分压电路:上拉 R1=10k,下拉 R2=20k

分压公式:

(V_{adc_pin}=V_{in_ext} \times \frac{R2}{R1+R2})

当外部输入 5V:(V_{adc_pin}=5 \times 20/(10+20)=3.33V),接近 3.3V,实际选型可微调电阻留余量。

✅ 硬件要点

  1. ADC 引脚旁并联 0.1μF 陶瓷滤波电容,抑制高频噪声;
  2. 分压电阻选用 1% 精度金属膜电阻;
  3. 模拟地和数字地单点连接,减少电源干扰;
  4. 输入电压严禁超过 3.3V,否则会烧毁 MCU。

三、软件滤波方案

硬件滤波只能抑制高频噪声,工业场景仍会存在小幅跳变。这里采用滑动平均滤波 ,占用资源小,裸机项目首选。

原理:保存 N 次采样值,求和取平均值,剔除瞬时尖峰干扰。

四、代码实现(HAL 库,精简版)

#include "stm32f1xx_hal.h"

#define ADC_CH ADC_CHANNEL_1

#define AVG_CNT 8 //滑动平均采样次数

uint16_t adc_bufAVG_CNT;

uint8_t buf_idx = 0;

//ADC单次读取

uint16_t ADC_ReadRaw(void)

{

HAL_ADC_Start(&hadc1);

HAL_ADC_PollForConversion(&hadc1, 10);

return HAL_ADC_GetValue(&hadc1);

}

//滑动平均滤波

uint16_t ADC_ReadFilter(void)

{

uint32_t sum = 0;

adc_bufbuf_idx++ = ADC_ReadRaw();

if(buf_idx >= AVG_CNT) buf_idx = 0;

复制代码
for(uint8_t i=0;i<AVG_CNT;i++)
{
    sum += adc_buf[i];
}
return sum / AVG_CNT;

}

//转换为实际电压,单位:mV

uint16_t ADC_GetVoltage(void)

{

uint16_t adc_val = ADC_ReadFilter();

// V(mV) = adc_val / 4095 * 3300

return (uint32_t)adc_val * 3300 / 4095;

}

调用示例:放在 1ms 定时器任务中非阻塞采集

//1ms定时回调

void TIM_IRQ_Callback(void)

{

static uint16_t cnt = 0;

cnt++;

if(cnt >= 10) //10ms采集一次

{

cnt = 0;

uint16_t vol_mv = ADC_GetVoltage();

}

}

标准库极简版本(可选)

uint16_t ADC_ReadRaw(void)

{

ADC_SoftwareStartConvCmd(ADC1, ENABLE);

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

return ADC_GetConversionValue(ADC1);

}

五、工程踩坑总结

  1. 读数一直固定不变:检查 ADC 通道配置、引脚模式是否设置为模拟输入;
  2. 数值跳动很大:优先查硬件,确认 0.1uF 滤波电容、电源纹波,再加大滤波采样点数;
  3. 电压计算结果偏差:不要直接用 3.3 浮点数运算,嵌入式尽量用整数运算防止精度损失;
  4. 分压电阻选错:电阻不能太小,否则传感器负载过大;不能太大,ADC 采样阻抗不足,推荐 10k~100k 区间;
  5. 不要在中断里长时间采样,ADC 读取尽量放到主循环或者定时任务。

六、选型拓展

  • 低速传感器(温湿度、电池电压):单通道查询采集 + 滑动平均;
  • 多路模拟信号:ADC DMA 多通道连续采样;
  • 高精度需求:增加外部基准源 TL431,替代片内 3.3V 参考。
相关推荐
星栖与芯1 小时前
LiteOS-M 切换汇编逐行图解(4):中断三件套与 HalTaskSchedule 触发
汇编·stm32·单片机·嵌入式硬件·harmonyos
G***技7 小时前
告别物联网碎片化:杰和LH707+LM2-100-V0联合方案给出标准答案
人工智能·嵌入式硬件
SKH.8 小时前
ARM汇编
嵌入式硬件·arm
深圳市恒锐丰科技杨生9 小时前
EG2134 300V 三相独立半桥栅极驱动芯片|屹晶 EGmicro
嵌入式硬件·硬件工程
朝发如雪9 小时前
快速掌握单片机基础(1)(嵌入式基本概念)
单片机
szxinmai主板定制专家9 小时前
【嵌入式实战】RK3588+GMSL多路相机采集方案|SerDes长距离低延时视频流落地教程
人工智能·单片机·机器人·边缘计算·zynq
LCG元9 小时前
STM32F103 SPI 驱动 W5500 以太网模块实战:硬件协议栈寄存器体系、Socket 状态机避坑与 TCP 吞吐实测
stm32·单片机·嵌入式硬件
Zhang.Yi10 小时前
STM32-SPI
stm32·单片机·嵌入式硬件
en.en..10 小时前
网络分层封装 与 TCP粘包的因果关系
网络·单片机·嵌入式硬件
天空'之城10 小时前
单片机基础核心知识点汇总(三十九)
单片机·嵌入式硬件