ADC 模拟信号采集(电位器、电压传感器)

STM32 ADC 模拟信号采集(电位器、电压传感器)

STM32 ADC(模数转换器)用于 采集模拟信号,如 电位器、电压传感器、温度传感器。本教程介绍 STM32 ADC 的工作原理、配置方法、代码实现,并进行 电压读取 & 电位器调节 实验。


1. STM32 ADC 简介

STM32 的 ADC 具有以下特点:

  • 12 位分辨率(默认,可设 6/8/10 位)
  • 支持单次转换、连续转换、DMA 传输
  • 支持内部参考电压(Vref)、芯片温度传感器
  • 支持多个通道,最多 16 个(取决于芯片型号)

💡 常见应用

  • 电压检测(读取传感器电压)
  • 温度采集(NTC 热敏电阻、内置温度传感器)
  • 电位器控制(旋转电位器,控制 LED 亮度)

2. 硬件连接

本实验使用 电位器(可变电阻),将其 中间端连接 ADC 输入端口,调节旋钮可改变输入电压。

STM32 引脚 连接
3.3V 电位器 VCC
GND 电位器 GND
PA0 (ADC_IN0) 电位器中间端

📌 输入电压范围:0V ~ 3.3V


3. STM32CubeMX 配置 ADC

📌 3.1 选择 ADC 输入通道

  1. 打开 STM32CubeMX
  2. 选择 ADC1
  3. 通道选择:IN0(PA0)
  4. 模式选择:单次转换
  5. 采样时间:239.5 cycles(提高精度)
  6. 分辨率:12bit
  7. 转换模式:单次

📌 3.2 时钟设置

  • 选择 APB2 72MHz
  • ADC 采用 12MHz 采样速率

4. 代码实现

📌 4.1 初始化 ADC

adc.c 生成如下代码:

void MX_ADC1_Init(void) {
    ADC_ChannelConfTypeDef sConfig = {0};

    /** 配置 ADC1 基本参数 */
    hadc1.Instance = ADC1;
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc1.Init.ContinuousConvMode = DISABLE;  // 单次转换
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 1;
    HAL_ADC_Init(&hadc1);

    /** 配置通道 */
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

📌 4.2 读取 ADC 数值

方法 1:单次读取

uint16_t Read_ADC(void) {
    HAL_ADC_Start(&hadc1);                     // 开始转换
    HAL_ADC_PollForConversion(&hadc1, 10);      // 等待转换完成
    uint16_t value = HAL_ADC_GetValue(&hadc1); // 获取 ADC 值
    HAL_ADC_Stop(&hadc1);                      // 关闭 ADC
    return value;
}

📌 12 位 ADC 范围:0 ~ 4095(对应 0V ~ 3.3V)

方法 2:转换为实际电压

float Get_Voltage(void) {
    uint16_t adc_value = Read_ADC();
    float voltage = (adc_value / 4095.0) * 3.3;
    return voltage;
}

📌 读取电压值,单位 V(伏特)。


📌 4.3 连续读取(定时模式)

while (1) {
    float voltage = Get_Voltage();
    printf("电压值:%.2fV\r\n", voltage);
    HAL_Delay(500);  // 500ms 读取一次
}

📌 在串口调试助手(如 SSCOM)可看到电压变化。


5. 使用 ADC + PWM 控制 LED

我们可以 使用电位器调节 LED 亮度

  1. 读取 ADC 值(0~4095)
  2. 映射到 PWM 占空比(0~100%)
  3. 控制 TIM2 的 PWM 输出

📌 5.1 代码实现

while (1) {
    uint16_t adc_value = Read_ADC();
    uint16_t pwm_duty = adc_value * 999 / 4095;  // 映射到 0~999
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_duty);
    HAL_Delay(100);
}

📌 旋转电位器 → PWM 变化 → LED 亮度变化


6. ADC + DMA(自动采样)

如果需要 高速采集数据(如音频采样),可使用 DMA 方式

  1. 配置 ADC 触发 DMA 传输
  2. 数据自动存入缓冲区

📌 6.1 配置 DMA

  • STM32CubeMX:启用 DMA1_Channel1,源设为 ADC1

📌 6.2 代码实现

uint16_t adc_buffer[10];  // 存储 10 个 ADC 采样值

void Start_ADC_DMA(void) {
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, 10);
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    if (hadc->Instance == ADC1) {
        float voltage = (adc_buffer[0] / 4095.0) * 3.3;
        printf("DMA 采集电压:%.2fV\r\n", voltage);
    }
}

📌 DMA 可连续采集,不占用 CPU 资源。


7. 总结

STM32 ADC 可采集电压、电流、温度等模拟信号
可结合 PWM 控制 LED 亮度、电机转速
支持单次采集、中断、DMA(适用于高速数据)
电位器实验:转动旋钮 → 电压变化 → LED 亮度变化

 

💡 建议新手先实现单次 ADC 采集,再学习 DMA 高速模式! 🚀

评论
列表