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 参考。
相关推荐
Zw-awa10 小时前
八路循迹模块的 DO:先让小车沿着线跑起来
stm32
黑妹天下第一乖11 小时前
第09讲 · 多媒体与音频 SDK:硬件编解码与端侧语音
人工智能·嵌入式硬件·深度学习·机器人·音视频·iot
comyccccc12 小时前
LM2596电源PCB布局布线全解析学习笔记
单片机·嵌入式硬件
恒锐丰科技林技术员13 小时前
EG2122 半桥栅极驱动芯片原理与工程应用解析
经验分享·嵌入式硬件·硬件工程
qq_4017004114 小时前
FreeRTOS 堆内存管理源码剖析:释放一块内存,空闲块数量反而变少了?
单片机·freertos
新晨单片机设计15 小时前
S017C-基于STM32汽车防酒驾系统(心率、血氧、短信)【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·防酒驾报警系统
fly_sunnn16 小时前
STM32-GPIO输出以及按键控制LED&光敏传感器控制蜂鸣器
stm32·单片机·嵌入式硬件
数字新视界16 小时前
U位资产管理系统发布全面数字化监控解决方案
嵌入式硬件·物联网·系统架构·机房管理·动力与环境监控系统
qq_4017004118 小时前
FreeRtos:SysTick的功能分析
单片机·嵌入式硬件
zbyyd19 小时前
i.MX6ULL 裸机开发|GT9147 触控 + SPI 与 ADXL345 加速度传感器驱动
单片机·嵌入式硬件