【STM32实战】ADC详解:模拟信号采集到数据处理全程指南
一、ADC 是什么?为什么需要它?
在嵌入式系统中,我们常遇到需要处理模拟信号的场景:
这些连续变化的模拟量无法直接被 STM32 的数字电路处理,而 **ADC(模数转换器)** 就是搭建 “模拟世界” 与 “数字世界” 的桥梁。
STM32 的 ADC 模块能将 0~3.3V 的模拟电压转换为 12 位数字值(0~4095),精度高、速度快,是传感器数据采集的核心组件。
二、STM32 ADC 核心特性(以 F103 系列为例)
1. 关键参数
2. 硬件连接要点
三、实战一:单通道电压采集(电位器调节 LED 亮度)
需求分析
实现步骤(CubeMX + HAL 库)
1. 在 CubeMX 中配置 ADC
① 新建工程:选择 STM32F103C8,启用 ADC1 通道 0(PA0)。
② 配置 ADC1:
③ 生成代码:确保勾选 “Generate ADC initialization”。
2. 编写 ADC 采集与 PWM 控制代码
① 在 main.c 中定义变量:
uint16_t adcValue = 0; // 存储ADC转换结果
uint16_t pwmValue = 0; // PWM占空比(0~999)
② 初始化 ADC 并启动转换
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM3_Init(); // 预配置TIM3用于PWM输出
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // 启动PWM
while (1) {
HAL_ADC_Start(&hadc1); // 启动ADC转换
HAL_ADC_PollForConversion(&hadc1, 100); // 等待转换完成(超时100ms)
adcValue = HAL_ADC_GetValue(&hadc1); // 获取转换结果
// 将ADC值(0~4095)映射为PWM占空比(0~999)
pwmValue = (uint16_t)(adcValue / 4.096);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwmValue); // 更新PWM占空比
HAL_Delay(50); // 控制采样频率
}
}
关键公式
Voltage = adcValue × 3.3V / 4096四、实战二:多通道同步采集(温湿度 + 光照强度)
需求分析
实现步骤(DMA + 扫描模式)
1. CubeMX 配置
① 启用 ADC1 多通道:勾选 ADC1_IN0(光照)、ADC1_IN1(温度)、ADC1_IN2(湿度)。
② 配置扫描模式:
③ 启用 DMA:
uint16_t adcBuffer[3]。2. 代码逻辑(DMA 传输)
uint16_t adcBuffer[3]; // 存储3通道数据
int main(void) {
HAL_Init();
MX_ADC1_Init();
HAL_ADC_Start_DMA(&hadc1, adcBuffer, 3); // 启动DMA传输,采集3通道数据
while (1) {
// 处理数据:adcBuffer[0]=光照,adcBuffer[1]=温度,adcBuffer[2]=湿度
// 例如:通过串口打印数据
printf("Light: %d, Temp: %d, Humidity: %d\r\n",
adcBuffer[0], adcBuffer[1], adcBuffer[2]);
HAL_Delay(1000);
}
}
优势解析
五、高级技巧:ADC 校准与抗干扰
1. 硬件校准
HAL_ADCEx_Calibration_Start(&hadc1); // 在初始化后调用校准函数
软件滤波(中值滤波)
uint16_t filterBuffer[10]; // 缓存10次采样值
uint16_t getFilteredValue() {
for (int i=0; i<9; i++) filterBuffer[i] = filterBuffer[i+1];
filterBuffer[9] = HAL_ADC_GetValue(&hadc1);
// 排序后取中值
for (int i=0; i<9; i++) {
for (int j=i+1; j<10; j++) {
if (filterBuffer[i] > filterBuffer[j]) {
uint16_t temp = filterBuffer[i];
filterBuffer[i] = filterBuffer[j];
filterBuffer[j] = temp;
}
}
}
return filterBuffer[5]; // 返回第5大的值
}
六、常见问题与解决方案
1. 转换结果始终为 0 或 4095
2. 多通道数据错乱
HAL_ADC_Start_DMA(&hadc1, buffer, 3)。3. 精度不足
七、总结:ADC 的应用边界与扩展
通过本文,你已掌握:
未来方向:
下一篇预告:《STM32 通信实战:USART 串口与物联网模块的互联互通》
(关注我,解锁设备联网技能~)
互动问题:你在 ADC 采集中遇到过最棘手的干扰问题是什么?欢迎在评论区讨论! 🔌
作者:星宇CY