ADC 模块通用初始化配置步骤(MCU 通用:STM32、GD32、CH32、RISC-V MCU 都适用)
先理清核心概念:ADC = 模拟数字转换器;涉及时钟、GPIO、ADC 内核、采样时序、触发方式、数据读取五大块。
前置前提:ADC 依赖时钟,必须先打开 ADC 外设时钟!
完整标准配置流程(推荐代码执行顺序)
1. 配置 ADC 输入 GPIO 引脚
- 打开 GPIO 端口时钟
- 将对应引脚设置为 模拟输入模式(Analog)
- 禁止上拉 / 下拉电阻!上下拉会引入直流电流,干扰模拟电压
- 关闭引脚数字输入缓冲(很多芯片模拟模式自动关闭)
重点:模拟信号线尽量远离高速数字信号线,减少干扰;必要时外部加 RC 滤波。
2. 使能 ADC 外设时钟 + 配置 ADC 内核时钟
- RCC 打开 ADC 时钟门控
- 设置 ADC 预分频,得到 ADC 工作时钟
ADCCLK⚠️ 硬性约束:ADCCLK 不能超过芯片手册规定最大时钟! 例:很多 12bit ADC 最大 36MHz、部分 24MHz,超频会造成采样不准、噪声变大。
区分两个容易混淆时钟:
- APB 总线时钟:寄存器读写用
- ADCCLK:ADC 转换内核工作时钟
3. ADC 基础内核参数配置
- 选择 ADC 分辨率:6/8/10/12/16bit
- 数据对齐:左对齐 / 右对齐(决定读取数据时怎么处理)
- 开启 / 关闭 ADC 连续转换模式、扫描模式
- 单次转换:触发一次,转换一次,停止
- 连续转换:转换完成立刻自动开始下一轮
- 扫描模式:多路通道依次轮流转换(多通道采集必备)
- 设置采样周期(采样保持时间 SMP)
非常关键!外部信号源阻抗大,必须加长采样周期,否则采样值偏低、波动大。每个通道可以独立配置采样时间。
4. 通道配置
- 选择 ADC 通道编号(IN0/IN1…)绑定对应引脚
- 多通道扫描模式下:配置通道序列、转换顺序、序列长度
5. 选择转换触发方式(二选一)
方式 A:软件触发(最简单)
软件写寄存器直接启动转换。适合低速采集。
方式 B:硬件触发(定时器触发 / 外部引脚触发)
常用:TIM 定时触发 ADC,实现周期性等间隔采样(信号采集、示波器类场景首选)
- 选择触发源(TIMx_CH、外部 EXTI 等)
- 设置触发极性:上升沿 / 下降沿触发
6. 中断 / DMA 配置(按需选配)
方案 1:查询模式(最简单,不推荐高频采样)
转换完成后轮询 EOC 转换完成标志位读取数据。
方案 2:ADC 中断模式
- 使能转换完成中断 / EOS 序列结束中断
- 配置 NVIC 中断优先级
- 在中断服务函数读取 ADC 数据
方案 3:DMA 搬运(多通道、高速采集首选)
- 打开 DMA 时钟
- 配置 DMA 方向:外设→内存
- 设置 DMA 地址:ADC_DR 寄存器地址 + 内存缓存地址
- 循环模式 / 普通模式、数据宽度
- 开启 DMA 请求,ADC 转换完成自动把数据搬运到内存,无需 CPU 干预
7. 使能 ADC 模块
所有参数配置完成后,打开 ADC 电源 / 使能 ADC
注意:部分芯片 ADC 使能后需要等待稳定时间。
8. 启动转换,采集数据
- 软件触发:置位 SWSTART 启动
- 硬件触发:等待定时器触发信号自动转换
9. 读取转换结果 + 可选后处理
- 等待转换完成标志
- 读取 ADC 数据寄存器 DR
- 根据参考电压,将原始 AD 值换算成实际电压:
\(V_{in} = \frac{AD_{val}}{2^{res}} \times V_{ref}\)
10. 可选高级配置
- 内部参考电压、温度传感器、VBAT 通道开启(需要单独使能内部通道)
- ADC 看门狗(模拟阈值监测,高于 / 低于阈值产生中断)
- 过采样(Oversample):多次采样平均,提高有效分辨率、降低噪声
- 差分输入配置(部分支持差分 ADC,抑制共模干扰)
- ADC 校准!【重中之重】
STM32/GD32 等绝大多数 MCU:上电后必须执行 ADC 自校准,消除偏移误差,否则零点不准。
最简流程一句话总结
配置 GPIO 模拟输入 → 开启 ADC 时钟 + 设置 ADC 预分频时钟 → 配置分辨率、对齐、采样周期、单通道 / 扫描模式 → 选择触发方式 →(按需配置 DMA / 中断)→(执行 ADC 自校准)→ 使能 ADC → 启动转换 → 读取 AD 数值。
高频踩坑清单
- GPIO 没设成模拟输入、开启上下拉 → 数值漂移不准
- ADCCLK 超过规格上限 → 噪声巨大
- 采样周期太短,信号源阻抗高 → AD 读数偏低
- 忘记 ADC 自校准 → 零点偏移
- 多通道没开启扫描模式,只会采集第一个通道
- DMA 没开启、地址配置错误,读不到数据
- 使用内部通道(温度传感器、VREFINT)忘记使能内部开关
- 频繁开关 ADC,每次开启建议重新校准
- 参考电压不稳定,没有滤波电容,采样波动大
对照实例(STM32F1/F4 典型流程)
\(V_{in} = \frac{AD\_val}{4096} \times V_{ref}\) ❌ 缺点:几乎没有缺点,常规项目默认选右对齐。
2. 左对齐(Left-aligned)
有效数据靠最高位摆放,低位补 0 12bit 数据向左挪 4 位,末尾填充 4 个 0
plaintext
bit15 ~ bit4 | bit3 ~ bit0
1010 1011 1100 | 0 0 0 0
寄存器读到的值:0xABC0
左对齐怎么还原真实 AD 值?
需要右移 4 位
c
运行
uint16_t raw = ADC->DR;
uint16_t adc_val = raw >> 4;
3. 左对齐存在的意义(什么时候用?)
核心场景:想直接把 ADC 高有效位当做 16bit DAC/PWM 输入,或者方便有符号差分 ADC 运算
场景 1:差分 ADC(有符号采样)
很多差分 ADC 输出带符号(最高位是符号位) 左对齐时,符号位正好落在 16bit 寄存器 bit15 位置,符合标准有符号 int16 格式:
直接强制转换成
int16_t就能做正负电压运算,非常方便。 这是左对齐最大用途!
场景 2:直接截取高几位使用
如果你只关心高 8 位精度: 左对齐模式下直接读取 DR 的高字节,不需要移位运算。
4. 一张对比表(12bit ADC)
表格
| 项目 | 右对齐 | 左对齐 |
|---|---|---|
| 采样值 0xABC 在 DR 中 | 0x0ABC | 0xABC0 |
| 获取真实 AD 值 | 直接读取,无需移位 | val >> 4 |
| 单端普通电压采集 | ⭐推荐首选 | 不推荐,多一次移位 |
| 差分有符号 ADC 采集 | 不方便 | ⭐适合 |
| 数据格式 | 无符号自然存放 | 高位对齐,适配 int16 |
5. 高频踩坑点
极简建议
拓展延伸:如果是 16bit ADC
寄存器正好填满,左右对齐没有区别;只有有效位 < 寄存器宽度时,对齐设置才有意义。
- GPIO 配置为模拟输入
- RCC 开启 ADC 时钟,配置 ADC 预分频
- 设置采样时间 SMPx
- 选择通道、扫描模式(多通道)
- 选择软件触发 / TIM 触发
- 开启 DMA(可选)
- 执行 ADC 校准
- 使能 ADC
- 软件启动转换
- 查询 / 中断 / DMA 获取 AD 值
-
ADC 左对齐 VS 右对齐(通俗易懂 + 实例)
先建立前提: ADC 输出原始采样值是 N bit(常见 12bit),但是ADC 数据寄存器 DR 一般是 16bit 宽度。 12bit 的有效数据,放在 16bit 寄存器里,就产生两种摆放方式:右对齐 / 左对齐。
约定例子:12bit ADC,采样得到数值 =
0xABC(二进制1010 1011 1100) DR 寄存器:16bit(bit15 ~ bit0)1. 右对齐(Right-aligned,绝大多数人首选)
有效数据靠最低位摆放,高位补 0
plaintext
bit15 bit14 ... bit12 | bit11 ~ bit0 0 0 0 | 1010 1011 1100寄存器读到的值:
0x0ABC✅ 优点:
- 读到的值直接就是原始 ADC 数值,不用移位;
- 电压计算公式直接套用:
- 配置左对齐,但代码仍然直接拿 DR 的值代入电压公式 → 数值偏大 16 倍,电压计算完全错误!
- 代码写死按照右对齐解析,实际寄存器配置成左对齐,数据全部异常。
- 单端采集、普通电压检测:一律右对齐
- 差分 ADC、需要正负信号、使用 int16 处理采样数据:选择左对齐
更多推荐

所有评论(0)