STM32-ADC
一、ADC 是什么
ADC 的全称是 Analog-to-Digital Converter,即模拟/数字转换器。
单片机本身处理的是数字量,而现实世界中的很多信号都是模拟量,例如电压、温度、光照、压力、电流等。ADC 的作用就是把连续变化的模拟电压转换成单片机能够处理的数字量。
典型数据流可以理解为:
传感器 -> ADC -> 单片机 -> 控制 / 显示 / 通信 / 存储
例如电位器输出 0 到 3.3 V 的模拟电压,STM32 ADC 可以把它转换为 0 到 4095 的数字量。
二、常见 ADC 类型
常见 ADC 类型包括并联比较型和逐次逼近型。
1. 并联比较型 ADC
并联比较型 ADC 通常由分压部分、比较部分和编码部分组成。
| 特点 | 说明 |
|---|---|
| 优点 | 转换速度最快 |
| 缺点 | 成本高、功耗高、分辨率较低 |
并联比较型适合高速场景,但硬件资源消耗较大。
2. 逐次逼近型 ADC
逐次逼近型 ADC 通常由控制电路、数码寄存器、D/A 转换器和电压比较器组成。
| 特点 | 说明 |
|---|---|
| 优点 | 结构简单、功耗较低 |
| 缺点 | 转换速度相对较慢 |
STM32 内部 ADC 通常属于逐次逼近型 ADC。它通过逐位逼近的方式,把输入模拟电压转换为数字结果。
3. 分辨率与采样速度的矛盾
ADC 的分辨率和采样速度往往存在矛盾:
分辨率越高,通常采样速率越低
采样速率越高,通常对分辨率和精度会有更多限制
工程中需要根据实际需求权衡。例如按键电压、电池电压这类慢变化信号不需要很高采样率,而高速波形采集则更关注采样速度。
三、ADC 关键参数
1. 分辨率
分辨率表示 ADC 能辨别的最小模拟量,通常用二进制位数表示,例如 8 位、10 位、12 位、16 位等。
以 12 位 ADC 为例:
数字量范围 = 0 ~ 4095
总刻度数 = 2^12 = 4096
如果参考电压为 3.3 V,则最小刻度约为:
最小刻度 = 3.3 / 4096 ≈ 0.000805 V
也就是约 0.805 mV。
2. 转换时间
转换时间表示完成一次 A/D 转换所需的时间。
转换时间越短,单位时间内能完成的采样次数越多,采样率也越高。
STM32 ADC 的转换时间主要和以下因素有关:
-
ADC 工作时钟频率
-
采样时间
-
ADC 分辨率
3. 精度
精度不是简单等于分辨率。
分辨率只说明 ADC 结果有多少个刻度,而精度还会受到多种误差影响,例如:
-
ADC 本身误差
-
参考电压误差
-
模拟输入噪声
-
温度变化
-
PCB 走线和电源质量
-
传感器误差
因此,12 位 ADC 不代表实际测量一定能达到 12 位有效精度。
4. 量化误差
ADC 用离散数字量近似表示连续模拟量,这个过程会产生量化误差。
可以简单理解为:模拟电压落在两个数字刻度之间时,ADC 只能选择其中一个数字值表示它,因此必然存在误差。
四、ADC 参考电压与输入范围
STM32 ADC 模拟部分通常由 VDDA、VSSA、VREF+、VREF- 等信号决定。
| 信号 | 作用 |
|---|---|
| VDDA | ADC 模拟电源 |
| VSSA | ADC 模拟地 |
| VREF+ | ADC 正参考电压 |
| VREF- | ADC 负参考电压 |
常见使用中:
VREF- = 0 V
VREF+ = 3.3 V
ADC输入范围 = 0 V ~ 3.3 V
输入电压必须满足:
VREF- <= VIN <= VREF+
如果输入电压超过 ADC 允许范围,可能导致转换结果错误,严重时还可能损坏芯片。因此测量高于 3.3 V 的信号时,必须使用分压、电压跟随、隔离或保护电路。
五、ADC 输入通道
STM32 ADC 通过多个输入通道连接外部引脚或内部信号。
常见通道来源包括:
-
外部 GPIO 模拟输入
-
内部温度传感器
-
内部参考电压
-
VBAT 或其他内部测量通道
使用外部引脚作为 ADC 输入时,需要将对应 GPIO 配置为模拟输入模式,避免数字输入结构影响采样结果。
六、规则组与注入组
STM32 ADC 通道转换分为规则组和注入组。
1. 规则组
规则组是最常用的转换组。
特点:
-
最多可配置 16 个转换通道。
-
转换顺序由规则序列寄存器
SQRx控制。 -
适合普通周期采样、连续采样和 DMA 采集。
规则组转换结果保存在:
ADCx_DR
2. 注入组
注入组可以理解为优先级更高的一组转换。
特点:
-
最多可配置 4 个转换通道。
-
转换顺序由注入序列寄存器
JSQR控制。 -
可以在规则组转换过程中插入执行。
注入组转换结果保存在:
ADCx_JDRy, y = 1 ~ 4
普通 ADC 采样场景下,优先掌握规则组即可。
七、ADC 触发源
ADC 转换需要触发源启动。
常见触发方式包括:
| 触发方式 | 说明 |
|---|---|
| 软件触发 | 程序调用函数启动转换 |
| ADON 位触发 | F1 中再次写 ADON 位可启动规则组转换 |
| 外部事件触发 | 由定时器、外部事件等触发 ADC 转换 |
规则组和注入组都可以使用外部触发,但具体可选触发源与芯片系列和 ADC 实例有关。
在工程中,软件触发适合低速、按需采样;定时器触发适合固定采样频率的场景。
八、ADC 转换时间
ADC 完成一次转换需要时间。
转换时间主要由采样时间和转换周期组成。
可以简单理解为:
总转换时间 = 采样时间 + ADC内部转换时间
以 12 位 ADC 为例,内部转换通常需要固定若干 ADC 时钟周期,再加上用户配置的采样时间。
如果采样时间设置为 239.5 个 ADC 时钟周期,且 ADC 时钟合适,一次转换时间可能达到几十微秒级。
采样时间不是越短越好。采样时间过短时,ADC 采样电容可能还没有稳定到输入电压,导致转换结果偏差变大。高阻抗信号源尤其需要更长的采样时间。
九、ADC 数据寄存器与数据对齐
规则组转换结果存放在:
ADCx_DR
注入组转换结果存放在:
ADCx_JDR1 ~ ADCx_JDR4
ADC 数据可以设置为右对齐或左对齐。
| 对齐方式 | 特点 |
|---|---|
| 右对齐 | 常用,读取结果更直观 |
| 左对齐 | 便于某些定点计算或兼容高位数据处理 |
大多数应用中使用右对齐即可。
十、ADC 中断与 DMA
1. EOC 转换结束标志
规则通道转换结束后,会产生 EOC 标志。
程序可以通过以下方式获取结果:
-
轮询等待转换完成。
-
开启转换完成中断。
-
使用 DMA 自动搬运结果。
2. DMA 请求
规则组每个通道转换结束后,除了可以产生中断外,还可以产生 DMA 请求。
使用 DMA 的目的,是及时把转换好的数据传输到指定内存中,防止数据被覆盖,也减少 CPU 频繁读取 ADC 数据寄存器的负担。
DMA 特别适合:
-
连续采样
-
多通道扫描采样
-
高采样率采集
-
固定长度采样缓存
十一、单次转换、连续转换和扫描模式
ADC 常见模式包括单次转换模式、连续转换模式和扫描模式。
1. 单次转换模式
单次转换模式只触发一次转换。
转换完成后 ADC 停止,需要下一次触发才会再次转换。
适合:
-
按键触发采样
-
偶尔读取电池电压
-
低频传感器采样
2. 连续转换模式
连续转换模式下,ADC 完成一次转换后会自动开始下一次转换。
适合:
-
持续采集某个模拟量
-
配合 DMA 自动更新采样结果
-
需要实时监测的信号
3. 扫描模式
关闭扫描模式时,ADC 只转换规则序列或注入序列中选中的第一个通道。
开启扫描模式时,ADC 会按序转换序列中配置的多个通道。
4. 模式组合
| 模式组合 | 效果 |
|---|---|
| 单次转换 + 不扫描 | 只转换一个通道一次 |
| 单次转换 + 扫描 | 按序转换多个通道一次 |
| 连续转换 + 不扫描 | 只转换一个通道,转换完成后自动进入下一次 |
| 连续转换 + 扫描 | 按序转换多个通道,完成后自动进入下一轮 |
还有一种不连续采样模式,在 F1 手册中也称为间断模式,通常只适用于扫描模式。它可以把完整扫描序列拆成多个小段触发执行。
十二、单通道 ADC 采集
单通道采集是 ADC 最基础的使用方式。
典型目标:
采集某个模拟输入通道的电压
读取 ADC 数字量
换算为实际电压值
以 12 位 ADC、VREF+ = 3.3 V 为例:
最小刻度 = 3.3 / 4096
输入电压 = ADC_Value * 3.3 / 4096
配置步骤
使用 HAL 库进行单通道 ADC 采集时,典型流程如下:
-
配置 ADC 工作参数并执行校准:
HAL_ADC_Init();
HAL_ADCEx_Calibration_Start();
- 完成 ADC MSP 初始化:
HAL_ADC_MspInit();
MSP 初始化通常包括 GPIO、ADC 时钟、NVIC 等配置。
-
配置 ADC 通道参数:
HAL_ADC_ConfigChannel();
-
启动 A/D 转换:
HAL_ADC_Start();
-
等待规则通道转换完成:
HAL_ADC_PollForConversion();
-
获取 ADC 转换结果:
HAL_ADC_GetValue();
这种方式适合低速采样和简单测试。
十三、单通道 ADC + DMA 采集
当需要连续采集单个通道时,可以使用 ADC + DMA。
典型配置:
连续转换模式
不使用扫描模式
DMA 将 ADCx_DR 中的数据搬运到内存变量或数组
配置步骤
典型流程如下:
-
初始化 DMA:
HAL_DMA_Init();
-
将 DMA 句柄和 ADC 句柄关联:
__HAL_LINKDMA();
-
配置 ADC 工作参数并执行校准:
HAL_ADC_Init();
HAL_ADCEx_Calibration_Start();
-
完成 ADC MSP 初始化:
HAL_ADC_MspInit();
-
配置 ADC 通道参数:
HAL_ADC_ConfigChannel();
-
配置 DMA 中断优先级并使能中断:
HAL_NVIC_SetPriority();
HAL_NVIC_EnableIRQ();
-
编写 DMA 中断服务函数:
void DMAx_Channely_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_xxx);
}
-
启动 DMA 并开启传输完成中断:
HAL_DMA_Start_IT();
-
启动 ADC DMA 转换:
HAL_ADC_Start_DMA();
使用 DMA 时,要注意缓冲区长度、DMA 数据宽度、ADC 数据对齐和采样频率。
十四、多通道 ADC + DMA 采集
多通道采集通常使用扫描模式配合 DMA。
典型配置:
连续转换模式
使用扫描模式
规则序列配置多个通道
DMA 将每个通道结果依次搬运到数组中
例如配置 6 个通道,则 DMA 缓冲区通常也需要至少 6 个元素:
uint16_t adc_buf[6];
每一轮扫描完成后,缓冲区中的数据对应各通道转换结果。
需要注意:
-
通道顺序由规则序列决定。
-
DMA 数组下标要和通道顺序对应。
-
多通道总采样周期会比单通道更长。
-
每个通道可以根据输入阻抗设置合适采样时间。
十五、过采样与求均值
过采样和求均值可以在一定程度上提高 ADC 有效分辨率,并降低随机噪声影响。
1. 过采样基本思路
如果希望提高 N 位分辨率,需要提高采样次数,并对多次采样结果求和后右移。
常见结论:
提高 N 位分辨率,需要右移 N 位
例如,12 位 ADC 希望提高 4 位,得到近似 16 位结果,需要进行 256 次采样:
采样次数 = 4^N = 4^4 = 256
处理方式:
256 次采样结果求和 -> 右移 4 位 -> 得到提高分辨率后的结果
2. 注意事项
过采样不是万能的。
需要满足:
-
输入信号变化不能太快。
-
采样频率足够高。
-
系统存在一定随机噪声,否则提升有限。
-
累加变量位宽要足够,避免溢出。
例如 12 位 ADC 最大值为 4095,256 次累加最大为:
4095 * 256 = 1048320
因此累加变量至少应使用 32 位。
十六、内部温度传感器
STM32 内部通常集成温度传感器,可通过 ADC 内部通道读取。
使用内部温度传感器时,基本流程是:
-
使能内部温度传感器通道。
-
配置 ADC 对内部通道采样。
-
读取 ADC 数字量。
-
换算为传感器输出电压。
-
根据芯片手册公式换算温度。
需要注意:
-
内部温度传感器精度有限,更适合芯片温度趋势监测。
-
不适合作为高精度环境温度计。
-
不同 STM32 系列的温度换算公式可能不同。
-
采样时间通常需要设置得较长,保证内部通道采样稳定。
十七、光敏传感器采集思路
光敏二极管的核心是 PN 结,对光照强度敏感。
它具有以下特点:
| 概念 | 说明 |
|---|---|
| 单向导电性 | 工作时通常需要加反向电压 |
| 暗电流 | 无光照时反向电流很小 |
| 光电流 | 有光照时,光照越强,反向电流越大 |
实际电路中,可以利用光电流变化,并串联电阻,把电流变化转换为电压变化,再由 ADC 读取。
常见处理方式:
光照变化 -> 光敏器件电流变化 -> 电阻上电压变化 -> ADC采样 -> 换算光强等级
由于光敏二极管响应通常不是严格线性的,工程上常把 ADC 结果映射为 0 到 100 的光照强度等级,而不是直接计算绝对光照值。
更多推荐

所有评论(0)