【STM32实战】ADC详解:模拟信号采集到数据处理全程指南

一、ADC 是什么?为什么需要它?

在嵌入式系统中,我们常遇到需要处理模拟信号的场景:

  • 光敏电阻随光线变化的电压值
  • 电位器旋转时的电阻变化量
  • 温度传感器输出的电流信号
    这些连续变化的模拟量无法直接被 STM32 的数字电路处理,而 **ADC(模数转换器)** 就是搭建 “模拟世界” 与 “数字世界” 的桥梁。
    STM32 的 ADC 模块能将 0~3.3V 的模拟电压转换为 12 位数字值(0~4095),精度高、速度快,是传感器数据采集的核心组件。
  • 二、STM32 ADC 核心特性(以 F103 系列为例)

    1. 关键参数

  • 分辨率:12 位(可识别 3.3V/4096≈0.8mV 的电压变化)。
  • 转换速度:最大 1MHz 时钟下,转换时间约 1μs(适合高频采样)。
  • 通道数量:最多 16 个外部通道 + 2 个内部通道(温度传感器、参考电压)。
  • 工作模式
  • 单次转换:转换一次后停止(适合按键检测等偶发场景)。
  • 连续转换:循环采样(适合实时数据监测)。
  • 扫描模式:依次转换多个通道(如同时采集温湿度、光照强度)。
  • 2. 硬件连接要点

  • 输入范围:0~VREF+(通常接 3.3V,由 VDDA 供电)。
  • 抗干扰:模拟信号引脚需接去耦电容(如 100nF),减少高频噪声。
  • 引脚复用:如 PA0~PA7 可作为 ADC 通道 0~7,需在 CubeMX 中配置为 “模拟输入” 模式。
  • 三、实战一:单通道电压采集(电位器调节 LED 亮度)

    需求分析

  • 目标:通过电位器调节输入电压,ADC 采集后转换为数字值,控制 LED 亮度(PWM 实现)。
  • 硬件:STM32F103C8T6 开发板、电位器、LED。
  • 电路连接
  • 电位器中间引脚接 PA0(ADC 通道 0),两端分别接 3.3V 和 GND。
  • LED 接 PC13(PWM 控制,参考前序定时器教程)。
  • 实现步骤(CubeMX + HAL 库)

    1. 在 CubeMX 中配置 ADC

    ① 新建工程:选择 STM32F103C8,启用 ADC1 通道 0(PA0)。
    ② 配置 ADC1

  • 模式:单次转换,非扫描模式。
  • 分辨率:12 位。
  • 采样时间:55.5 周期。
  • 使能通道 0:在 “Channels” 中勾选 ADC1_IN0。
  • ③ 生成代码:确保勾选 “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
  • PWM 映射:将 0~4095 的 ADC 值压缩到 0~999,实现亮度线性调节。
  • 四、实战二:多通道同步采集(温湿度 + 光照强度)

    需求分析

  • 目标:同时采集 3 路模拟信号(温度、湿度、光照),用 DMA 实现非阻塞传输。
  • 硬件:STM32F103C8T6、DHT11(单总线,需 ADC 采集电压)、光敏电阻、热敏电阻。
  • 实现步骤(DMA + 扫描模式)

    1. CubeMX 配置

    ① 启用 ADC1 多通道:勾选 ADC1_IN0(光照)、ADC1_IN1(温度)、ADC1_IN2(湿度)。
    ② 配置扫描模式

  • 勾选 “Scan Conversion Mode”(扫描模式)。
  • 设置通道转换顺序:IN0→IN1→IN2,循环扫描。
    ③ 启用 DMA
  • 选择 DMA 通道 1(ADC1 专用),传输方向:外设到存储器。
  • 存储器地址:定义数组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);
      }
    }

    优势解析

  • DMA 非阻塞:CPU 无需等待 ADC 转换,可同时处理其他任务(如串口通信、按键检测)。
  • 扫描模式:自动按顺序采集多通道,避免软件轮询的延迟误差。
  • 五、高级技巧:ADC 校准与抗干扰

    1. 硬件校准

  • 原因:ADC 内部元件存在制造误差,校准可提高精度。
  • 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

  • 原因
  • 引脚未正确连接(浮空或短路)。
  • ADC 时钟未使能(检查 CubeMX 的 RCC 配置)。
  • 解决:用万用表测量引脚电压,确保在 0~3.3V 范围内,并重新生成代码。
  • 2. 多通道数据错乱

  • 原因:DMA 缓冲区大小与通道数不匹配。
  • 解决:DMA 传输数量需等于通道数,如 3 通道则HAL_ADC_Start_DMA(&hadc1, buffer, 3)
  • 3. 精度不足

  • 优化
  • 增大采样时间(CubeMX 中设置为 239.5 周期,适合高精度场景)。
  • 启用过采样(通过 ADC_CR1 的 OVERSAMPLING_RATIO 配置)。
  • 七、总结:ADC 的应用边界与扩展

    通过本文,你已掌握:

  • 单通道采集:电位器、传感器等基础应用。
  • 多通道扫描 + DMA:高效处理多路模拟信号。
  • 抗干扰技巧:校准与滤波提升数据可靠性。
  • 未来方向

  • 结合 DMA 和定时器,实现周期性多通道采样(如工业数据监控)。
  • 搭配 DAC(数模转换器),构建闭环控制系统(如自动温控风扇)。
  • 下一篇预告:《STM32 通信实战:USART 串口与物联网模块的互联互通》
    (关注我,解锁设备联网技能~)

    互动问题:你在 ADC 采集中遇到过最棘手的干扰问题是什么?欢迎在评论区讨论! 🔌

    作者:星宇CY

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【STM32实战】ADC详解:模拟信号采集到数据处理全程指南

    发表回复