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 输入通道
- 打开 STM32CubeMX
- 选择 ADC1
- 通道选择:IN0(PA0)
- 模式选择:单次转换
- 采样时间:239.5 cycles(提高精度)
- 分辨率:12bit
- 转换模式:单次
📌 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 亮度:
- 读取 ADC 值(0~4095)
- 映射到 PWM 占空比(0~100%)
- 控制 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 方式:
- 配置 ADC 触发 DMA 传输
- 数据自动存入缓冲区
📌 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 高速模式! 🚀