STM32 嵌入式 ADC 数据采集系统学习指南
多通道采集时通道间干扰严重。:采集值与实际值偏差较大。
一、学习路径规划
(一)基础理论阶段(1-2 周)
- 模拟电子技术基础复习
- 重点掌握运算放大器原理、RC 滤波电路、电桥电路等基础电路
- 理解分压原理、信号放大与电平转换的基本方法
2.数字电路基础补充
- 学习 ADC 模数转换的基本原理:采样、保持、量化、编码四个步骤
- 掌握奈奎斯特采样定理及其在实际工程中的应用
3.STM32 ADC 模块原理学习
- 阅读 STM32 数据手册中 ADC 部分,了解 ADC 的主要特性参数
- 学习 STM32 ADC 的工作模式:独立模式、扫描模式、连续转换模式等
- 理解 ADC 分辨率、采样率、参考电压等关键指标对采集精度的影响
(二)实践操作阶段(2-3 周)
- 开发环境搭建
- 安装 STM32CubeIDE 或 Keil MDK 开发环境
- 配置 STM32CubeMX 工具,掌握基本的工程创建流程
2.硬件平台准备
- 准备 STM32 开发板(推荐 STM32F103 或 STM32F4 系列)
- 配备基本的信号源和测量工具:函数发生器、万用表、示波器
3.基础实验操作
- 完成单个 ADC 通道的配置与数据采集实验
- 实现 ADC 多通道轮流采集功能
- 学习使用不同的触发方式:软件触发、定时器触发、外部中断触发
(三)进阶提高阶段(3-4 周)
- 硬件设计与优化
- 设计简单的信号调理电路,包括滤波、放大、电平转换
- 学习 PCB 设计中模拟部分的布局布线原则
- 实践模拟地与数字地的分离技术
2.数据处理算法实现
- 实现多种数字滤波算法:均值滤波、中值滤波、滑动平均滤波
- 学习 ADC 误差分析与校准方法
- 掌握实际工程中的数据处理与转换技巧
3.综合项目实践
- 完成温度采集系统设计与实现
- 尝试压力、湿度等其他物理量的采集系统开发
- 实现多通道同步采集系统
二、核心知识要点详解
(一)ADC 基础原理深入理解
- 采样定理的工程应用
- 实际应用中,为保证信号还原质量,通常取采样频率为信号最高频率的 3-5 倍
- 示例:采集音频信号(最高频率 20kHz),采样频率应设置为 80kHz 以上
2.量化误差计算
- 12 位 ADC 的量化单位:\(Q = V_{ref}/4096\)
- 量化误差范围:\(\pm Q/2\)
- 示例:3.3V 参考电压下,量化单位为 0.805mV,量化误差约为 ±0.4mV
(二)STM32 ADC 关键特性
- ADC 通道与引脚对应关系
- 以 STM32F103 为例,ADC1 通道 0 对应 PA0 引脚,通道 1 对应 PA1 引脚,依此类推
- 不同 STM32 型号的 ADC 通道与引脚映射关系可能不同,需查阅对应数据手册
2.采样时间与转换速度的关系
- 采样时间设置:ADC_SAMPLETIME_71CYCLES_5 表示采样时间为 71.5 个时钟周期
- 转换时间计算:转换时间 = 采样时间 + 12.5 个时钟周期(12 位转换)
- 示例:时钟频率为 14MHz 时,采样时间 71.5 周期约为 5.1us,总转换时间约为 6.0us,采样率约为 167kHz
(三)HAL 库编程核心技巧
- ADC 初始化流程优化
// 优化后的ADC初始化函数
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
// ADC基础配置
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 时钟分频设置
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12位分辨率
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 禁用扫描模式(单通道)
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV; // 转换序列结束标志
hadc1.Init.ContinuousConvMode = ENABLE; // 连续转换模式
hadc1.Init.NbrOfConversion = 1; // 转换通道数
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
hadc1.Init.DMAContinuousRequests = DISABLE; // 禁用DMA请求
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // 溢出处理方式
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
// 通道配置
sConfig.Channel = ADC_CHANNEL_10; // 选择通道10(PA0)
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; // 通道排名
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5; // 采样时间设置
sConfig.Offset = 0; // 偏移量设置
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
2.高效数据采集方法
// 带数字滤波的数据采集函数
uint16_t Get_ADC_Value_Filtered(void)
{
uint32_t adc_sum = 0;
uint16_t adc_buffer[10] = {0};
uint8_t i, j, temp;
// 采集10个数据
for(i = 0; i < 10; i++)
{
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
adc_buffer[i] = HAL_ADC_GetValue(&hadc1);
}
HAL_ADC_Stop(&hadc1);
}
// 中值滤波:排序
for(i = 0; i < 9; i++)
{
for(j = 0; j < 9 - i; j++)
{
if(adc_buffer[j] > adc_buffer[j+1])
{
temp = adc_buffer[j];
adc_buffer[j] = adc_buffer[j+1];
adc_buffer[j+1] = temp;
}
}
}
// 去掉最大值和最小值,取中间8个值的平均值
for(i = 1; i < 9; i++)
{
adc_sum += adc_buffer[i];
}
return (uint16_t)(adc_sum / 8);
}
三、实践项目指导
(一)基础项目:模拟电压采集显示系统
- 项目需求
- 采集 0-3.3V 模拟电压信号
- 在 LCD 上实时显示电压值
- 精度要求达到 0.01V
2.硬件设计
- 信号输入:通过电位器分压提供 0-3.3V 可调电压
- 显示模块:OLED 或 LCD1602
- 参考电压:使用 STM32 内部参考电压或外部高精度参考源
3.软件实现
// 电压转换与显示函数
void Display_Voltage(void)
{
uint16_t adc_value;
float voltage;
char display_buffer[20];
// 获取ADC值
adc_value = Get_ADC_Value_Filtered();
// 转换为电压值(参考电压3.3V)
voltage = (float)adc_value * 3.3 / 4096;
// 格式化显示字符串
sprintf(display_buffer, "Voltage: %.2fV", voltage);
// 在LCD上显示
LCD_Clear();
LCD_SetCursor(0, 0);
LCD_PrintString(display_buffer);
}
(二)进阶项目:多通道温度采集系统
- 系统架构
- 传感器:4 路 PT100 热电阻
- 信号调理:4 路电桥电路 + 仪表放大器
- 显示模块:LCD 触摸屏
- 通信接口:USB 或蓝牙,用于数据上传

2.温度计算优化
// 改进的温度计算函数(考虑线性补偿)
float Calculate_Temperature(uint16_t adc_value, uint8_t channel)
{
float voltage, resistance, temperature;
float A = 3.9083e-3, B = -5.775e-7;
float compensation = 0;
// 根据通道选择不同的补偿系数(考虑通道差异)
switch(channel)
{
case 0: compensation = 0.1; break;
case 1: compensation = 0.2; break;
case 2: compensation = 0.15; break;
case 3: compensation = 0.05; break;
default: compensation = 0;
}
// 计算电压和电阻
voltage = (float)adc_value * 3.3 / 4096;
resistance = 100 * voltage / (3.3 - voltage);
// 计算温度(使用二次方程求根公式)
temperature = (-A + sqrt(A*A - 4*B*(1 - resistance/100))) / (2*B);
// 加入补偿
temperature += compensation;
return temperature;
}
四、学习资源推荐
(一)硬件资源
- 开发板

- STM32F103C8T6 开发板(入门级,性价比高)
- STM32F407VET6 开发板(进阶型,功能更强大)
2.传感器套件

- 模拟传感器套件(包含温度、压力、湿度等传感器)
- PT100 热电阻及调理电路模块
(二)软件资源
- 开发工具
- STM32CubeMX(图形化配置工具)
- STM32CubeIDE(集成开发环境)
- Keil MDK(经典嵌入式开发工具)

2.参考代码
- STM32 官方 HAL 库例程
- STM32Cube_FW_F1 固件库(针对 F1 系列)
- 开源项目中的 ADC 应用代码(如 GitHub 上的相关项目)
(三)学习资料
- 书籍
- 《STM32 库开发实战指南》
- 《深入浅出 STM32》
- 《模拟电子技术基础》(童诗白)
- 《数字电子技术基础》(阎石)
2.在线教程
- 慕课网:STM32 单片机原理及应用
- 哔哩哔哩:STM32 ADC 数据采集专题教程
- 博客园:STM32 开发系列博客(推荐关注嵌入式相关博主)
五、常见问题与解决方案
(一)硬件问题
- 问题现象:ADC 采集值波动较大,不稳定
- 可能原因:电源纹波大、接地不合理、信号线受干扰
- 解决方案:
- 增加电源滤波电容,使用低纹波电源
- 优化接地设计,确保模拟地与数字地正确连接
- 缩短信号线长度,必要时使用屏蔽线
2.问题现象:采集值与实际值偏差较大
- 可能原因:参考电压不准、信号调理电路误差、ADC 未校准
- 解决方案:
- 使用高精度参考源,并定期校准参考电压
- 检查信号调理电路参数,确保放大倍数正确
- 在程序中加入 ADC 校准函数,定期进行偏移校准
(二)软件问题
- 问题现象:ADC 转换速度达不到预期
- 可能原因:时钟配置不正确、采样时间设置过长、程序中存在阻塞
- 解决方案:
- 检查 ADC 时钟分频设置,确保时钟频率足够
- 优化采样时间设置,在精度和速度间找到平衡
- 改用 DMA 方式传输数据,避免 CPU 阻塞
2.问题现象:多通道采集时通道间干扰严重
- 可能原因:扫描模式配置不当、通道切换时间不足
- 解决方案:
- 合理配置扫描模式,确保通道切换时有足够的稳定时间
- 增加通道间的采样间隔,或使用独立的 ADC 模块进行采集
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)