ADC简介
什么是ADC?
ADC,全称:Analog-to-Digital Converter,指模拟/数字转换器

常见的ADC类型
| ADC电路类型 | 优点 | 缺点 |
| 并联比较型 | 转换速度最快 | 成本高、功耗高,分辨率低 |
| 逐次逼近型 | 结构简单,功耗低 | 转换速度较慢 |
并联比较型工作示意图
优点:转换速度快 缺点:成本高、功耗高、分辨率低
逐次逼近型工作示意图
优点:结构简单、低功耗 缺点:转换速度较慢
特点: 分辨率和采样速度相互矛盾, 分辨率越高,采样速率越低
ADC的特性参数
| 分辨率(刻度划分) | 表示ADC能辨别的最小模拟量,用二进制位数表示,比如:8、10、12、16位等 |
| 转换时间 | 表示完成一次A/D转换所需要的时间,转换时间越短,采样率就可以越高 |
| 精度(物理量的精准程度) | 最小刻度基础上叠加各种误差的参数,精度受ADC性能、温度和气压等影响 |
| 量化误差 | 用数字量近似表示模拟量,采用四舍五入原则,此过程产生的误差为量化误差 |
STM32各系列ADC的主要特性
| 主要特性 | F1 | F4 | F7 | H7 |
| ADC类型 | 逐次逼近型 | |||
| 分辨率 | 12位 | 6/8/10/12位 | 6/8/10/12位 | 8/10/12/14/16位 |
| ADC时钟频率 | 14MHz(max) | 36MHz(max) | ||
| 采样时间 | 采样时间越长, 转换结果相对越准确, 但是转换速度就越慢 | |||
| 转换时间 | 与ADC时钟频率、分辨率和采样时间等有关 | |||
| 供电电压 | VSSA :0V,VDDA :2.4V~3.6V(全速运行) | |||
| 参考电压 | VREF– :0V,VREF+一般为3.3V | |||
| 输入电压 | VREF–≤VIN≤VREF+ | |||
ADC工作原理
ADC框图简介(F1)

①参考电压/模拟部分电压
②输入通道
③转换序列
④触发源
⑤转换时间
⑥数据寄存器
⑦中断
ADC框图简介(F4)

①参考电压/模拟部分电压
②输入通道
③转换序列
④触发源
⑤转换时间
⑥数据寄存器
⑦中断
ADC框图简介(H7)

①VREF+电压
②ADC双时钟域架构
③输入通道
④转换序列
⑤触发源
⑥转换时间
⑦参考电压
⑧ADC核心
⑨数据寄存器
⑩中断
⑪通道预选控制信号
参考电压/模拟部分电压
ADC供电电源:VSSA、 VDDA (2.4V≤VDDA≤3.6V )
Vref+、Vref-参考电压
ADC输入电压范围:VREF–≤VIN≤VREF+(即0V≤VIN≤3.3V )
输入通道 F1为例
| ADC1 | IO | ADC2 | IO | ADC3 | IO |
| 通道0 | PA0 | 通道0 | PA0 | 通道0 | PA0 |
| 通道1 | PA1 | 通道1 | PA1 | 通道1 | PA1 |
| 通道2 | PA2 | 通道2 | PA2 | 通道2 | PA2 |
| 通道3 | PA3 | 通道3 | PA3 | 通道3 | PA3 |
| 通道4 | PA4 | 通道4 | PA4 | 通道4 | PF6 |
| 通道5 | PA5 | 通道5 | PA5 | 通道5 | PF7 |
| 通道6 | PA6 | 通道6 | PA6 | 通道6 | PF8 |
| 通道7 | PA7 | 通道7 | PA7 | 通道7 | PF9 |
| 通道8 | PB0 | 通道8 | PB0 | 通道8 | PF10 |
| 通道9 | PB1 | 通道9 | PB1 | 通道9 | 连接内部VSS |
| 通道10 | PC0 | 通道10 | PC0 | 通道10 | PC0 |
| 通道11 | PC1 | 通道11 | PC1 | 通道11 | PC1 |
| 通道12 | PC2 | 通道12 | PC2 | 通道12 | PC2 |
| 通道13 | PC3 | 通道13 | PC3 | 通道13 | PC3 |
| 通道14 | PC4 | 通道14 | PC4 | 通道14 | 连接内部VSS |
| 通道15 | PC5 | 通道15 | PC5 | 通道15 | 连接内部VSS |
| 通道16 | 连接内部温度传感器 | 通道16 | 连接内部VSS | 通道16 | 连接内部VSS |
| 通道17 | 连接内部Vrefint | 通道17 | 连接内部VSS | 通道17 | 连接内部VSS |
转换序列(F1为例)
A/D转换被组织为两组:规则组(常规转换组)和注入组(注入转换组) 规则组最多可以有16个转换,注入组最多有4个转换

规则组(Regular Group) 和注入组(Injected Group)
| 特性 | 规则组(Regular) | 注入组(Injected) |
|---|---|---|
| 设计目的 | 常规数据采集 | 高优先级中断性测量(如保护触发) |
| 通道数量 | 最多16通道(型号相关) | 最多4通道(J1-J4) |
| 转换顺序 | 线性顺序执行 | 可独立配置每个注入通道的转换顺序 |
| 触发方式 | 软件/硬件触发 | 支持硬件触发抢占(如定时器TRGO) |
| 数据寄存器 | 共用1个规则数据寄存器(DR) | 每个注入通道有独立数据寄存器(JDR1-4) |
| 中断事件 | EOC(转换结束) | JEOC(注入转换结束) |
规则组数据寄存器(DR)的覆盖机制
1. 单次转换模式(非连续)
-
行为:每次转换完成后,结果存储在
DR寄存器中,不会被覆盖,直到:- 用户读取
DR值(读取后硬件自动清除EOC标志) - 启动新的转换(手动或硬件触发)
- 用户读取
-
代码验证:
c
HAL_ADC_Start(&hadc1); // 启动单次转换 while(!HAL_ADC_PollForConversion(&hadc1, 10)); // 等待完成 uint32_t val1 = HAL_ADC_GetValue(&hadc1); // 读取第一次结果 delay_ms(1000); uint32_t val2 = HAL_ADC_GetValue(&hadc1); // val2 == val1(未被覆盖)
2. 连续转换模式
-
行为:
- 每次转换完成后立即开始下一次转换
- 新数据会覆盖
DR寄存器,但EOC标志在每次转换后都会置位 - 若未及时读取数据,前次结果将被丢失
-
风险点:
c
HAL_ADC_Start_IT(&hadc1); // 启动连续转换+中断 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { // 若中断处理太慢,可能导致数据被覆盖 uint32_t val = HAL_ADC_GetValue(hadc); }
3. DMA模式下的保护
- 优势:DMA自动搬运数据到指定内存,完全避免覆盖风险
c
uint32_t adc_buffer[100]; HAL_ADC_Start_DMA(&hadc1, adc_buffer, 100); // DMA循环存储
如何避免规则/注入数据混淆?
// 在DMA中断中区分数据来源
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if(hadc->Instance->SR & ADC_SR_JEOC) {
// 处理注入数据
} else {
// 处理规则数据
}
}
规则组和注入组执行优先级对比

规则序列和注入序列(F1为例)
| 规则序列寄存器控制关系汇总 | |||
| 寄存器 | 寄存器位 | 功能 | 取值 |
| SQR3 | SQ1 [ 4 : 0 ] | 设置第1个转换的通道 | 通道0~17 |
| SQ2 [ 4 : 0 ] | 设置第2个转换的通道 | 通道0~17 | |
| SQ3 [ 4 : 0 ] | 设置第3个转换的通道 | 通道0~17 | |
| SQ4 [ 4 : 0 ] | 设置第4个转换的通道 | 通道0~17 | |
| SQ5 [ 4 : 0 ] | 设置第5个转换的通道 | 通道0~17 | |
| SQ6 [ 4 : 0 ] | 设置第6个转换的通道 | 通道0~17 | |
| SQR2 | SQ7 [ 4 : 0 ] | 设置第7个转换的通道 | 通道0~17 |
| SQ8 [ 4 : 0 ] | 设置第8个转换的通道 | 通道0~17 | |
| SQ9 [ 4 : 0 ] | 设置第9个转换的通道 | 通道0~17 | |
| SQ10 [ 4 : 0 ] | 设置第10个转换的通道 | 通道0~17 | |
| SQ11 [ 4 : 0 ] | 设置第11个转换的通道 | 通道0~17 | |
| SQ12 [ 4 : 0 ] | 设置第12个转换的通道 | 通道0~17 | |
| SQR1 | SQ13 [ 4 : 0 ] | 设置第13个转换的通道 | 通道0~17 |
| SQ14 [ 4 : 0 ] | 设置第14个转换的通道 | 通道0~17 | |
| SQ15 [ 4 : 0 ] | 设置第15个转换的通道 | 通道0~17 | |
| SQ16 [ 4 : 0 ] | 设置第16个转换的通道 | 通道0~17 | |
| SQL [ 3 : 0 ] | 设置规则序列要转换的通道数 | 0~15 | |
| 注入序列寄存器控制关系汇总 | |||
| 寄存器 | 寄存器位 | 功能 | 取值 |
| JSQR | JSQ1 [ 4 : 0 ] | 设置第1个转换的通道 | 通道0~17 |
| JSQ2 [ 4 : 0 ] | 设置第2个转换的通道 | 通道0~17 | |
| JSQ3 [ 4 : 0 ] | 设置第3个转换的通道 | 通道0~17 | |
| JSQ4 [ 4 : 0 ] | 设置第4个转换的通道 | 通道0~17 | |
| JL [ 1 : 0 ] | 设置注入序列要转换的通道数 | 0~3 | |
注入序列的转换顺序是从JSQx[ 4 : 0 ](x=4-JL[1:0])开始
ADC采样基本流程
-
采样(Sampling)
- 通过采样保持电路(Sample-and-Hold, S/H)在固定时间点捕获输入电压。
- 关键参数:采样时间(
SamplingTime)需满足:tsampling≥tcharge=Rsource×CADC×ln(2N+1)tsampling≥tcharge=Rsource×CADC×ln(2N+1)
其中 RsourceRsource 为信号源阻抗,CADCCADC 为ADC输入电容,NN 为分辨率(如12位)。
-
保持 需要采样保持的原因是,电压是波动的,因此想要在转换过程中,保持稳定。就需要这个采样保持电路。整个过程耗费时间即为采样时间。
-
量化(Quantization)
- 将连续电压值离散化为有限数字值(如12位ADC的0~4095)。
-
转换(Conversion)
- 采用逐次逼近寄存器(SAR) 算法完成数字转换:
校准
- ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差
- 建议在每次上电后执行一次校准
- 启动校准前,ADC必须处于关电状态超过至少两个ADC时钟周期
校准过程是固定的,只需要注意调用即可。

数据对齐
数据寄存器是16位的,ADC是12位的,因此存在一个数据对齐的问题,以便正确获取数据。一般使用右对齐,直接得到转换结果。
注入组通道转换的数据值已经减去了在ADC_JOFRx寄存器中定义的偏移量,因此结果可以是一 个负值。SEXT位是扩展的符号值。 对于规则组通道,不需减去偏移值,因此只有12个位有效。

数据对齐常用于控制精度,如果后面的四位不要了,可以左对齐后只取高八位
触发源(F1)
触发转换的方法有两种:
(1)ADON位触发转换(仅限F1系列)
当ADC_CR2寄存器的ADON位为1时,再单独(其他位不可以改变)给ADON位写1,只能启动规则组转换
(2)外部事件触发转换
通过设置EXTSEL寄存器来选择控制源。


外部事件触发转换分为:规则组外部触发和注入组外部触发
触发源(F4/F7)
触发源(H7)
参考《STM32H7xx参考手册_V3(中文版).pdf》825页
转换时间(F1)
(1)如何设置ADC时钟?
(2)如何设置ADC转换时间?
ADC转换时间: TCONV = 采样时间 + (转换时间)12.5个周期
-
转换时间:
Tconversion=(分辨率位数+0.5)×TADC_CLKTconversion=(分辨率位数+0.5)×TADC_CLK
- 12位模式:12.5周期(默认)
- 10位模式:10.5周期(需配置
ADC_Resolution_10b) - 8/6位模式:8.5/6.5周期
采样时间可通过SMPx[2:0]位设置,x=0~17
SMP = 000:1.5个ADC时钟周期
SMP = 001:7.5个ADC时钟周期
SMP = 010:13.5个ADC时钟周期
SMP = 011:28.5个ADC时钟周期
SMP = 100:41.5个ADC时钟周期
SMP = 101:55.5个ADC时钟周期
SMP = 110:71.5个ADC时钟周期
SMP = 111:239.5个ADC时钟周期
举个例子:ADC时钟频率为12MHz时,ADC最短的转换时间是多少?
TCONV = 采样时间 + 12.5个周期 = 1.5个周期 + 12.5个周期 = 14个周期 = (1/12000000)∗14 s = 1.17us
转换时间(F4/F7)
(1)如何设置ADC时钟?

(2)如何设置ADC转换时间?
ADC转换时间(12位分辨率): TCONV = 采样时间 + 12个周期
采样时间可通过SMPx[2:0]位设置,x=0~18
SMP = 000:3个ADC时钟周期
SMP = 001:15个ADC时钟周期
SMP = 010:28个ADC时钟周期
SMP = 011:56个ADC时钟周期
SMP = 100:84个ADC时钟周期
SMP = 101:112个ADC时钟周期
SMP = 110:144个ADC时钟周期
SMP = 111:480个ADC时钟周期
举个例子:ADC时钟频率为21MHz时,ADC最短的转换时间是多少?
TCONV = 采样时间 + 12个周期 = 3个周期 + 12个周期 = 15个周期 = (1/21000000)∗15 s = 0.71us
转换时间(H7)
(1)如何设置ADC时钟?

(2)如何设置ADC转换时间?
ADC转换时间:TCONV = 采样时间(TSMPL) + 逐次逼近时间(TTSAR)
采样时间可通过SMPx[2:0]位设置,x=0~19
SMP = 000:1.5个ADC时钟周期
SMP = 001:2.5个ADC时钟周期
SMP = 010:8.5个ADC时钟周期
SMP = 011:16.5个ADC时钟周期
SMP = 100:32.5个ADC时钟周期
SMP = 101:64.5个ADC时钟周期
SMP = 110:387.5个ADC时钟周期
SMP = 111:810.5个ADC时钟周期
逐次逼近时间(TTSAR)和分辨率有关,RES[2:0]用于设置分辨率,如:16/14/12/10/8位
逐次逼近时间(TTSAR)和分辨率对应关系表:

举个例子:ADC时钟频率为32MHz时,分辨率为16位,ADC最短的转换时间是多少?
TCONV = TSMPL + TTSAR = (1.5 + 8.5)个ADC周期 = 10个ADC周期 = (1/32000000)∗10s = 0.31us
数据寄存器(F1)

由ADCx_CR2寄存器的ALIGN位设置数据对齐方式,可选择:右对齐或者左对齐
数据寄存器(F4/F7)

由ADCx_CR2寄存器的ALIGN位设置数据对齐方式,可选择:右对齐或者左对齐
数据寄存器(H7)

由OVSS[3:0]和LSHIFT[3:0]位域设置数据对齐方式,可选择:右对齐或者左对齐
中断
F1/F4/F7系列ADC中断事件汇总表:
| 中断事件 | 事件标志 | 使能控制位 |
| 规则通道转换结束 | EOC | EOCIE |
| 注入通道转换结束 | JEOC | JEOCIE |
| 设置了模拟看门狗状态位 | AWD | AWDIE |
| 溢出(F1没有) | OVR | OVRIE |
DMA请求(只适用于规则组)
规则组每个通道转换结束后,除了可以产生中断外,还可以产生DMA请求,我们利用DMA及时把转换好的数据传输到指定的内存里,防止数据被覆盖。
H7系列ADC中断类型

ADC转换模式
单次转换模式和连续转换模式
| CONT位 | 0 | 1 |
| 转换模式 | 单次转换模式 | 连续转换模式 |
| 转换组/转换模式 | 单次转换模式(只触发一次转换) | 连续转换模式(自动触发下一次转换) 注意:只有规则组才能触发该模式 |
| 规则组 | 转换结果被储存在ADC_DR EOC(转换结束)标志位被置1 如果设置了EOCIE位,则产生中断 然后ADC停止 | 转换结果被储存在ADC_DR EOC(转换结束)标志位被置1 如果设置了EOCIE位,则产生中断 |
| 注入组 | 转换结果被储存在ADC_DRJx JEOC(转换结束)标志位被置1 如果设置了JEOCIE位,则产生中断 然后ADC停止 | 转换结果被储存在ADC_DRJx JEOC(转换结束)标志位被置1 如果设置了JEOCIE位,则产生中断 自动注入:将JAUTO位置1 |
扫描模式
| SCAN位 | 0 | 1 |
| 扫描模式 | 关闭扫描模式 | 使用扫描模式 |
| 关闭扫描模式 | 使用扫描模式 |
| ADC只转换ADC_SQRx或ADC_JSQR选中的第一个通道进行转换 | ADC会扫描所有被ADC_SQRx或ADC_JSQR选中的所有通道 |
不同模式组合的作用
| 单次转换模式(不扫描) | 只转换一个通道,而且是一次,需等待下一次触发 |
| 单次转换模式(扫描) | ADC_SQRx 和ADC_JSQR 选中的所有通道都转换一次 |
| 连续转换模式(不扫描) | 只会转换一个通道,转换完后会自动执行下一次转换 |
| 连续转换模式(扫描) | ADC_SQRx 和ADC_JSQR 选中的所有通道都转换一次,并自动进入下一轮转换 |
举个例子:
| 单次转换模式(不扫描) | 使用ADC单通道,并要求进行一次转换 |
| 单次转换模式(扫描) | 使用ADC多通道,并要求所有通道都转换一次就停止 |
| 连续转换模式(不扫描) | 使用ADC单通道,并要求对该通道连续转换 |
| 连续转换模式(扫描) | 使用ADC多通道,并要求所有通道都转换一次后,自动启动下一轮转换 |
一种比较少用的模式:不连续采样模式(F1手册称为:间断模式),只适用在扫描模式下。
ADC工作模式
工作模式定义了ADC模块的全局运行方式,主要分为以下类型:
1. 独立模式(Independent Mode)
- 特点:单个ADC独立工作,不与其他ADC交互
- 配置方法:
c
hadc.Init.ScanConvMode = DISABLE; // 禁用扫描模式(单通道) hadc.Init.ContinuousConvMode = ENABLE; // 启用连续转换 - 适用场景:单通道或简单多通道采集
2. 多ADC协同模式(Dual/Triple Mode)
| 模式 | 触发方式 | 典型应用 |
|---|---|---|
| 交替模式 | 交替触发各ADC | 高速信号采集(如STM32H7) |
| 同步规则模式 | 同步转换相同通道 | 提高信噪比(求平均值) |
| 同步注入模式 | 注入组同步触发 | 关键信号冗余采集 |
- 配置示例(双重交替模式):
c
hadc1.Init.DualMode = ADC_DUALMODE_INTERL; hadc2.Init.TriggerControlledByADC = ADC_TRIGGER_CONTROLLED_BY_ADC1;
3. 过采样模式(Oversampling)
- 原理:硬件自动累加多次采样结果,提升分辨率
- 配置参数:
c
hadc.Init.OversamplingMode = ENABLE; hadc.Init.Oversample.Ratio = ADC_OVERSAMPLING_RATIO_16; hadc.Init.Oversample.RightBitShift = ADC_RIGHTBITSHIFT_4; - 优势:将12位ADC提升至14-16位有效分辨率
6840

被折叠的 条评论
为什么被折叠?



