笔记 / 嵌入式ADC采样模拟信号

引言

温度、湿度、压力、光线、声音这些物理量都是连续变化的模拟量,单片机只能处理 0 和 1 的数字量。ADC(模数转换器)负责把模拟量转换成数字量,是单片机采集这类信号的入口。下面按基本概念、核心参数、工作模式、HAL 配置示例、DMA 采集和常见问题依次展开。

一、ADC 基本概念

ADC(Analog to Digital Converter)将连续的模拟信号转换为离散的数字信号。转换过程包含四个步骤:

步骤说明
采样(Sampling)以固定时间间隔获取模拟信号的瞬时值
保持(Hold)用电容保持采样值,防止转换期间信号变化
量化(Quantization)将连续的模拟值划分为离散的数字级别
编码(Encoding)将量化结果以二进制形式输出

二、核心参数详解

1. 分辨率(Resolution)

  • STM32 F1/F4 系列:典型 12 位分辨率,输出范围 0 ~ 4095(2¹² - 1)
  • STM32 H7 系列:最高 16 位分辨率,过采样可达 26 位

LSB(最低有效位)计算公式:

LSB = Vref+ / 2^分辨率位数

以 12 位分辨率、参考电压 3.3V 为例:

LSB = 3.3V / 4096 ≈ 0.806mV
实际电压 = ADC转换值 × (3.3 / 4096)

2. 采样率(Sampling Rate)

关键参数F1 系列典型值说明
ADC 时钟最高14 MHz超过会降低精度
常用分频配置PCLK2 的 8 分频 = 9 MHzADCCLK 必须 ≤ 14MHz
最短采样周期1.5 个 ADCCLK 周期可编程范围:1.5 ~ 239.5 周期

总转换时间公式:

Tconv = 采样时间 + 12.5 个周期(逐次逼近固定时间)

最快转换时间(F1):Tconv = (1.5 + 12.5) × (1/12MHz) ≈ 1.17 μs

3. ADC 类型

STM32 采用逐次逼近型(SAR)ADC,在精度和速度之间取得良好平衡。逐次逼近的工作方式类似二分查找:从最高位开始,每次比较后把候选范围缩小一半,逐位确定转换结果。

三、工作模式

转换模式

模式说明
单次转换触发一次,执行一次转换后停止
连续转换一次触发后,不断循环转换
扫描模式按预设顺序轮流采集多个通道
间断模式分组间断地进行多通道转换

通道组

通道组通道数特点
规则通道组(Regular)最多 16 路正常运行,结果存于单个数据寄存器
注入通道组(Injected)最多 4 路类似中断,可打断规则通道转换

触发方式

  • 软件触发:代码直接启动转换
  • 外部事件触发:定时器、EXTI 外部中断等

四、HAL 库配置示例

单通道单次转换

// 1. 使能时钟
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

// 2. GPIO 配置为模拟输入
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// 3. ADC 初始化
ADC_HandleTypeDef hadc1;
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);

// 4. 配置通道
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

// 5. 读取转换值
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
uint16_t adc_value = HAL_ADC_GetValue(&hadc1);
float voltage = adc_value * (3.3f / 4096);

五、DMA 模式:多通道与高速采集

对于多通道或高速持续采集,推荐使用 DMA 循环传输模式,由 DMA 自动将 ADC 数据搬移到内存数组,无需 CPU 频繁干预:

// DMA 关键配置
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;              // 循环模式
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;  // ADC数据寄存器
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&adc_buffer; // 内存数组
DMA_InitStructure.DMA_BufferSize = 通道数量;

这样 ADC 持续采集,DMA 自动搬运,CPU 只需在需要时读取 adc_buffer 即可。

六、常见问题与注意事项

问题原因解决方案
外部阻抗过大导致误差分压电阻过大(MΩ 级),与内部 50kΩ 阻抗分压使用 ≤10kΩ 分压电阻,或加运放做阻抗变换
多通道串扰采样电容在通道切换时残留电荷增大通道间采样延时
引脚浮空外部无输入时引脚悬空加下拉电阻
扫描模式数据覆盖规则组只有一个数据寄存器及时读取或使用 DMA
ADC 时钟超频ADC 时钟 >14MHz正确配置分频因子

七、STM32 各系列 ADC 参数速查

指标STM32F1STM32F4STM32H7
分辨率12 bit12 bit16 bit
ADC 时钟最高14 MHz36 MHz36 MHz
最快转换时间≈ 1 μs≈ 0.5 μs更快
参考电压3.3V3.3V2.5V / 3.3V
LSB(12bit@3.3V)0.806 mV0.806 mV约 0.05 mV

总结

ADC 把连续变化的模拟量转换成离散的数字量,中间经过采样、保持、量化和编码四个步骤。分辨率决定能分辨的最小电压变化,采样时间和 ADC 时钟决定转换速度,多通道或高速采集则交给 DMA 循环搬运。这几个参数之间的取舍,是设计采样电路时要先确定的部分。