恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
STM32F103 ADC读电压:采样周期、DMA与校准全解析
首页
资讯中心
/
STM32F103 ADC读电压:采样周期、DMA与校准全解析
STM32F103 ADC读电压:采样周期、DMA与校准全解析
发布时间:2026/9/14 22:54:36
简介STM32(F103)的ADC读取电压程序是一份可直接编译运行的Keil MDK工程面向嵌入式初学者和需要实现模拟量采集的开发者。程序基于STM32F103标准外设库围绕12位ADC展开覆盖初始化、通道配置、采样时间选择、软件触发与连续转换、中断及DMA传输等关键步骤并提供电压值换算、内部参考校准、功耗控制与误差补偿的工程化处理思路能够帮助读者理清从模拟输入到数字输出的完整链路。压缩包共237个文件约3.98MB除C源码与H头文件外还包含启动文件、可烧录的hex文件、uvproj工程配置、map/lst调试信息以及htm/doc说明文档目录结构清晰便于直接下载后打开工程实验。工程内还包含GPIO、USART、定时器、外部中断、SysTick、DS18B20温度传感器和AT24CXX存储器等外设驱动方便扩展学习。已有1888人学习/下载适合对照实际项目反复调试快速上手STM32的ADC应用。1. F103 的 ADC 读电压为什么例程一堆你还得看这篇做 STM32 的人手里多半存着几个 ADC 例程F103 的 ADC 模块说简单也简单配个通道、设个采样周期、启动转换、读数据寄存器三步就完事。但真拿去做产品比如做个电池电压监测、做个 0-10V 传感器采集、或是给电机驱动板做母线电压采样你会发现读数飘、精度对不上、多通道数据串位、DMA 丢数据这些坑一个接一个。这篇不是把某个现成的STM32(F103)的ADC读取电压程序.rar内容复述一遍而是按工程上做 ADC 采集最常见的路径把 F103 的 ADC 寄存器配置、轮询/中断/DMA 三种读取方式、多通道扫描和数据处理完整讲清楚连带着讲采样周期怎么选、参考电压怎么处理、PCB 布局时 ADC 电源引脚要注意什么。新手能照着最小代码跑起来老手也能在参数取舍和校准细节里找到对自己有用的东西。2. 先从 F103 的 ADC 硬件结构说起搞清楚采样周期和时钟的边界2.1 F103 的 ADC 是逐次逼近型12 位分辨率但有效精度取决于外围STM32F103 内置的 ADC 是 12 位逐次逼近型SAR转换器ADC1 和 ADC2 各有 16 个外部通道ADC3 有 8 个103 的互联型产品上才是全套还有个内部温度传感器通道和 VREFINT 内部参考电压通道。逐次逼近的意思是把输入的模拟电压和一个由 DAC 生成的参考电压逐位比较从最高位到最低位一共比较 12 次每次比较需要一个 ADC 时钟周期。这个结构决定了转换时间有个固定下限不是你随便把时钟提上去就能变快的。F103 的 ADC 时钟源来自 APB2 总线时钟通过 RCC_CFGR 寄存器的 ADCPRE 位做 2/4/6/8 分频。而 ADC 模块本身最高只能跑到 14MHz这个上限写在数据手册的电气特性里超过它转换结果就不再保证单调性。所以如果你的系统时钟是 72MHzADC 时钟只有两种合理选择6 分频得 12MHz或者 8 分频得 9MHz。有些例程里写的是 4 分频得到 18MHz转换是能跑但精度已经不在数据手册保证范围内了做产品不建议这么用。ADC 的转换周期由采样阶段和比较阶段组成。采样阶段通过采样开关给内部采样电容充电充电时间由 SMPx 位决定可选 1.5、7.5、13.5、28.5、41.5、55.5、71.5、239.5 个 ADC 时钟周期。比较阶段固定是 12.5 个周期。所以总的转换时间就是采样周期 12.5个 ADC 时钟。举个例子ADC 时钟 12MHz采样周期用 55.5单次转换就是 68 个时钟约 5.67μs。很多初学者不理解为什么要分采样和转换两个阶段。采样阶段决定的是内部采样电容上的电压能不能跟上外部信号源。如果信号源内阻大采样时间短电容没充满就开始比较读出来的值会比实际电压偏低。尤其是直接用一个高阻分压器比如 100kΩ 以上的电阻分压接 ADC 输入时这个问题会非常明显。2.2 引脚和通道的映射关系配错 GPIO 模式是第一个坑F103 的 ADC 外部通道分布在 GPIOA、GPIOB、GPIOC 上比如 ADC1 的通道 0 在 PA0通道 1 在 PA1通道 4 在 PA4通道 10-15 在 PC0-PC5 上。做电压读取最常用的就是 PA0-PA7 这几个引脚。配置时 GPIO 必须设为模拟输入模式也就是 GPIOx_CRL 寄存器里 CNF 位设为 00、MODE 位设为 00。把人家的例程拿过来改通道号结果采集回来的数据永远是 0 或者乱跳十有八九是 GPIO 模式配错了。有些人习惯把所有引脚都配成推挽输出或者配成复用推挽ADC 输入引脚上一旦配了输出模式外部电压会被引脚内部的上拉或下拉电阻分压读数完全失真。模拟输入模式下引脚内部的上下拉电阻是断开的输入阻抗只由 ADC 内部采样结构决定。2.2.1 最小配置代码直接用寄存器操作用标准外设库或者 HAL 库可以几行代码完成配置但库函数封装太多层不利于理解时序关系。我通常用寄存器方式做 ADC 初始化代码短执行路径清晰调起来也直观。void ADC1_Init(void) { /* 1. 开启 GPIOA 和 ADC1 时钟 */ RCC-APB2ENR | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_ADC1EN; /* 2. PA0 设为模拟输入CNF00MODE00 */ GPIOA-CRL ~(0xFUL 0); /* 3. ADC 时钟分频72MHz / 6 12MHz */ RCC-CFGR | RCC_CFGR_ADCPRE_DIV6; /* 4. ADC1 上电关闭连续转换用软件触发 */ ADC1-CR2 ADC_CR2_ADON; ADC1-CR2 ~ADC_CR2_CONT; /* 5. 校准上电后必须做一次 */ ADC1-CR2 | ADC_CR2_RSTCAL; while (ADC1-CR2 ADC_CR2_RSTCAL); ADC1-CR2 | ADC_CR2_CAL; while (ADC1-CR2 ADC_CR2_CAL); /* 6. 规则序列第 1 个转换是通道 0 */ ADC1-SQR3 0; /* 7. 采样周期239.5 个周期适合高内阻信号源 */ ADC1-SMPR2 | (7UL 0); /* 8. 启动转换 */ ADC1-CR2 | ADC_CR2_SWSTART; }这段代码里几个关键点第 3 步的ADCPRE_DIV6宏在标准库头文件里对应寄存器位的值也可以在RCC-CFGR里直接写(2UL 14)6 分频是 14 位和 15 位组合的二进制的10。第 5 步校准必须在 ADC 上电之后做而且不能省略。校准的目的是修正内部电容阵列的失调误差不做的话零点会有几十个 LSB 的偏差。校准完成后要等硬件把 CAL 位清零才算真正结束。第 6 步把规则序列的第一个位置设为通道 0SQR3 寄存器的最低 5 位就是第一次转换的通道号。第 7 步设的是通道 0 的采样周期SMPR2 寄存器的[2:0]位对应通道 0。2.2.2 采样周期选择表照着这张表选就够了采样周期的选择直接关系到读数的准确性和转换速度给一张对应关系表方便在工程上直接查。SMPx 位值采样周期ADC 时钟总转换周期12MHz 下时间适用场景0001.514.01.17μs极低内阻信号源100Ω0017.520.01.67μs低内阻运放输出01013.526.02.17μs常规运放输出01128.541.03.42μs中等内阻传感器10041.554.04.50μs分压电阻在 10k 级别10155.568.05.67μs分压电阻在 50k 级别11071.584.07.00μs高内阻信号111239.5252.021.0μs源阻抗 100kΩ工程上最常见的误用就是无论什么信号源都用同一套采样周期结果低内阻的场景白白浪费了转换速度高内阻的场景读数全是噪声。选采样周期的基本原则是让采样电容完全充到源电压经验公式是采样时间需要大于(Rsource Rswitch) * Csample * 8左右F103 内部采样电容约 4pF开关电阻约 1kΩ。用一个 100kΩ 的电阻分压器直接接 ADC算下来需要约 3.3μs 的采样时间对应 41.5 周期以上。这个计算不精确但足够判断该选哪档。如果信号源内阻很高又不愿意把采样周期拖长正确的做法是在 ADC 引脚外面并联一个 100nF 到 1μF 的电容作为电荷缓冲。采样瞬间电容上的电压不会掉太多采样结束后再通过电阻慢慢充回来。这是 ADC 采样电路里最有价值的技巧之一能同时兼顾速度和精度。注意引脚电容不能太大否则外部信号会被电容和源阻抗构成低通滤波器拖慢了对快速变化信号的跟随能力。3. 单通道电压读取的三种实现方式轮询、中断、DMA3.1 轮询方式逻辑最简单适合低频采集轮询方式就是启动转换之后一直查状态寄存器的 EOC 位置位了就认为转换完成读数据。这种方式的优点是代码短、时序确定缺点是在转换期间 CPU 被占住不能做别的事。uint16_t ADC1_ReadSingle(void) { ADC1-CR2 | ADC_CR2_SWSTART; /* 启动转换 */ while (!(ADC1-SR ADC_SR_EOC)); /* 等待 EOC 置位 */ return (uint16_t)ADC1-DR; /* 读取结果 */ }读ADC1-DR这个动作本身就清除了 EOC 标志位所以这个函数每次调用只做一次转换返回 12 位右对齐的结果。F103 的 ADC 数据寄存器支持左对齐和右对齐默认硬件复位后是右对齐也就是数据存在[11:0]位读出来直接就是 0-4095 的整数。轮询函数返回之前外部引脚已经采样并完成比较所以返回值是稳定的。轮询方式的适用边界系统里只有一路 ADC 采集或者采集周期远大于转换时间。比如每 100ms 读一次电池电压转换才花 5μs完全没必要上中断或者 DMA。把ADC1_ReadSingle()放在主循环里用定时器或者系统节拍控制调用频率就能满足需求。如果系统里同时有多个任务主循环里等 EOC 的这几微秒虽然不长但在高优先级任务抢 CPU 的场景下会引入不确定延时这时候就要考虑中断方式。3.2 中断方式转换和数据读取解耦中断方式下ADC 转换完成会触发中断在中断服务函数里读数据、清标志。这样做的好处是主程序完全不用关心转换什么时候结束可以继续做其他事。volatile uint16_t adc_value 0; volatile uint8_t adc_done 0; void ADC1_IRQHandler(void) { if (ADC1-SR ADC_SR_EOC) { adc_value ADC1-DR; /* 读 DR 同时清除 EOC */ adc_done 1; } } void ADC1_StartInt(void) { ADC1-CR1 ~ADC_CR1_EOCIE; /* 先关中断改配置 */ ADC1-CR2 | ADC_CR2_SWSTART; /* 启动转换 */ ADC1-CR1 | ADC_CR1_EOCIE; /* 使能 EOC 中断 */ }使用中断方式时有个小细节SWSTART位置 1 之后EOCIE 如果已经使能转换结束就会立刻进中断。但如果你在中断服务函数里又做滤波计算或者要切换通道处理时间要尽量短不然会影响下一次转换的启动时机。中断标志位在ADC1-DR被读取之后自动清零这一点和 GPIO 的外部中断不一样GPIO 的中断标志需要软件主动清除而 ADC 的 EOC 标志是读数据寄存器时硬件自动清除的。有些例程里会先读SR再读DR这是为了确认 EOC 标志确实置位了。如果直接用ADC1-DR读数据也会得到最近一次转换结果但有可能读到的是旧数据因为 EOC 还没置位你就读了。所以正确顺序是查到 EOC 置位然后读 DR。3.3 DMA 方式采样数据不经过 CPU连续转换必须配 DMAF103 的 ADC1 和 ADC2 各有独立的 DMA 请求ADC1 的 DMA 通道是 DMA1 的 Channel1。DMA 方式的典型场景是连续转换模式ADC 自己不断启动转换每完成一次就通过 DMA 把数据搬到内存缓冲区整个过程 CPU 完全不参与。等缓冲区满了DMA 传输完成中断再通知 CPU 统一处理数据。#define ADC_BUF_LEN 64 uint16_t adc_buf[ADC_BUF_LEN]; void ADC1_DMA_Init(void) { /* ADC1 配置连续转换模式 DMA 请求 */ ADC1-CR2 | ADC_CR2_CONT | ADC_CR2_DMA; ADC1-CR2 | ADC_CR2_SWSTART; /* DMA1 通道 1 配置 */ DMA1_Channel1-CPARDR (uint32_t)ADC1-DR; /* 外设地址 */ DMA1_Channel1-CMARDR (uint32_t)adc_buf; /* 内存地址 */ DMA1_Channel1-CNDTR ADC_BUF_LEN; /* 传输次数 */ DMA1_Channel1-CCR DMA_CCR1_MEM2MEM_DISABLE | DMA_CCR1_PL_VERY_HIGH | DMA_CCR1_MSIZE_16BIT | DMA_CCR1_PSIZE_16BIT | DMA_CCR1_MINC_ENABLE | DMA_CCR1_DIR | DMA_CCR1_TCIE; DMA1_Channel1-CCR | DMA_CCR1_EN; NVIC_EnableIRQ(DMA1_Channel1_IRQn); } void DMA1_Channel1_IRQHandler(void) { if (DMA1-ISR DMA_ISR_TCIF1) { /* 传输完成 */ DMA1-IFCR | DMA_IFCR_CTCIF1; /* adc_buf 里已经有了 64 个最近采样值 */ } }这段配置里最关键的是方向位DMA_CCR1_DIRDMA 从外设读数据写到内存所以方向位是外设到内存也就是1。MINC位使能后DMA 每搬运一次数据内存地址自动加 2 字节16 位数据宽度64 个数据依次填到数组里。CNDTR是剩余传输计数DMA 自己会递减传输完成中断触发后这个值回到 0。如果要做循环采集在中断服务函数里重新给CNDTR赋值再重新使能 DMA 通道。注意CNDTR写入之前必须先关闭 DMA 通道直接写是无效的这是 F103 的 DMA 设计上的一个硬限制。DMA 方式下 ADC 的 EOC 中断不能开。如果开了 EOCIE每转换完一次都会进一次中断让你读数据清标志这正好破坏了 DMA 自动搬运的流程。EOC 标志位会由 DMA 控制器读取数据而清除用户程序不需要管它。我用 DMA 连续采样 64 个点做软件平均读出来的电压值波动能压到 1 个 LSB 以内。3.4 三种读取方式怎么选对照一个决策表采集场景推荐方式原因主循环里定时读单路电压轮询代码简单CPU 占用低多任务系统不想阻塞主循环中断转换和业务逻辑解耦连续监测电压波形DMACPU 零参与可循环缓冲多通道循环扫描DMA通道切换和数据搬运全自动轮询、中断、DMA 不是互斥的实际工程里可以组合中断方式读单次转换结果DMA 方式做连续采样。比如电源管理模块里开机用一次轮询读初始电压正常运行用 DMA 周期采样这两个逻辑可以同时存在只要不打架就行。清楚每种方式的适用边界比背代码有意义。4. 多通道扫描、校准参差和 ADC 数据漂移的排查方向4.1 多通道规则扫描DMA 数组的顺序和通道顺序一一对应F103 的规则通道最多可以排 16 个转换序列每次转换按 SQR 寄存器里定义的顺序依次执行。做多通道电压读取时DMA 方式天然适合DMA 按转换完成顺序把数据依次写入缓冲区第 0 个数据对应序列中的第一个通道第 1 个数据对应第二个通道依此类推。void ADC1_MultiChannel_DMA_Init(void) { /* 规则序列共 3 个转换 */ ADC1-SQR1 | (2UL 20); /* L[3:0] 2序列长度 3 */ ADC1-SQR3 (0UL 0) | /* 第 1 个通道 0 */ (1UL 5) | /* 第 2 个通道 1 */ (2UL 10); /* 第 3 个通道 2 */ /* 三个通道都用 239.5 周期采样 */ ADC1-SMPR2 | (7UL 0) | (7UL 3) | (7UL 6); ADC1-CR2 | ADC_CR2_CONT | ADC_CR2_DMA; ADC1-CR2 | ADC_CR2_SWSTART; }这里SQR1的[23:20]位是规则序列长度注意序列长度要减一写入。比如 3 个通道写入2。SQR3 寄存器第 1 个转换的通道号在[4:0]位第 2 个在[9:5]位第 3 个在[14:10]位互不重叠可以一次写整个寄存器。SMPR2 寄存器每 3 位对应一个通道的采样周期通道 0 是[2:0]通道 1 是[5:3]通道 2 是[8:6]所以写76就设了通道 2 的采样周期。多通道扫描要注意的一个典型问题通道之间的串扰。如果通道 0 接的是 3.3V通道 1 接的是 0.5V在连续扫描模式下通道 0 采样时采样电容充到 3.3V接下来通道 1 采样如果采样时间不够长电容上的电荷没有完全放掉并充到 0.5V通道 1 的读数就会偏高。解决办法是把采样周期调大或者在每次转换之间插入足够长的间隔。DMA 连续扫描模式下没有间隔所以高阻抗信号源的多通道采集特别容易看到数据漂移。实际问题排查时把通道 0 和通道 1 短接在一起测如果读数一致说明通道配置没问题问题出在源阻抗和采样时间的匹配上。4.2 校准不是可选项内部校准流程必须走一遍F103 的 ADC 自校准可以在上电后任何时候执行但必须在 ADC 上电ADON 位为 1且没有进行转换时。校准过程分两步先写 RSTCAL 位开始初始化校准寄存器等硬件清 RSTCAL 表示初始化完成再写 CAL 位开始实际校准等硬件清 CAL 表示校准完成。void ADC1_Calibrate(void) { ADC1-CR2 | ADC_CR2_RSTCAL; while (ADC1-CR2 ADC_CR2_RSTCAL); ADC1-CR2 | ADC_CR2_CAL; while (ADC1-CR2 ADC_CR2_CAL); }校准不会完全消除误差它主要修正内部电容阵列的失调。剩余误差还有增益误差和参考电压误差这两项在校准流程之外。如果对精度要求高就要做两点校准用精密电压源给 ADC 两个已知电压点比如 0.5V 和 3.0V读回两个原始值算出斜率和偏置然后用线性校正公式处理所有读数。这个校正系数建议存在 Flash 里上电时读出来用。F103 没有带出厂校准值的选项和 F0/F3 系列不同所以标定这一步不能省。内部温度传感器通道也在这类程序里经常被顺带读出来做芯片温度监测。F103 的 ADC1 通道 16 连接内部温度传感器需要在 ADC_CR2 寄存器里置位 TSVREFE 位才能使能传感器供电然后按正常通道读就行了。温度传感器的电压和温度大致呈线性关系但每个芯片的偏置不同精度有限做趋势监测可以做精确温度测量还是得外部传感器。4.3 ADC 数据漂移的排查路径先软件后硬件做 ADC 数据采集最头疼的问题就是数据漂移。示波器量引脚电压很稳定但单片机读回来的数字一直在跳。这种问题按优先级排查90% 的情况集中在三处。第一处是电源噪声。F103 的 ADC 参考电压直接取自 VDDA如果 VDDA 上有纹波转换结果必然跟着抖。ADC 电路设计里最基础的一条原则是VDDA 引脚和 VREF 引脚如果有的话要用磁珠或至少一个 10Ω 电阻和 VDD 隔开旁边接 1μF 和 100nF 两个电容PCB 上这个电容要尽量靠近 MCU 引脚。F103 的 LQFP48 封装没有独立的 VREF参考电压就是 VDDA所以 VDDA 的干净程度直接决定 ADC 精度。第二处是参考地。VSSA 和数字地 VSS 在芯片内部是连通的但外部 PCB 上如果模拟地和数字地走线太长太细模拟信号回流路径和数字开关电流回流路径共用一段走线ADC 转换瞬间数字逻辑翻转产生的噪声就会叠加到模拟地上。常见做法是在 PCB 上做模拟地和数字地单点连接或者至少保证 ADC 引脚附近的地是完整的。第三处是源端驱动能力。前面说过采样电容需要从外部信号源吸取电荷如果信号源内阻太大采样造成的电压降就会在每次转换时表现出来转换结果表现为随机噪声而不是偏置。判断方法把采样周期从 1.5 改成 239.5如果读数变得稳定说明源阻抗太高。正确做法是采样周期放大加引脚并联电容必要时加一级运放缓冲ADC 采样电路设计里运放缓冲是精度要求高的场景的标准做法。4.4 软件滤波别只求稳住要求稳得住原始特征软件滤波是 ADC 数据处理的最后一道工序。常见做法有两种中值滤波和滑动平均。中值滤波对尖峰脉冲干扰有很好的抑制效果比如工业现场电磁干扰导致的偶发毛刺取 5 个数据中中间的那个值能把毛刺直接滤掉。滑动平均适合信号本身有轻微随机噪声的场景比如电池电压、温度等缓变信号取最近 N 次采样的平均值N 一般取 8 到 32。注意滑动平均值会引入延迟N 越大延迟越大快速响应场景要用加权滑动平均或者用一阶低通滤波/* 一阶低通滤波alpha 取 0.1 ~ 0.3 */ uint16_t ADC_LowPass(uint16_t new_value, uint16_t old_value, uint8_t alpha) { return (uint16_t)(((uint32_t)alpha * new_value (256 - alpha) * old_value) 8); }这个滤波函数的参数要注意old_value 是上一次滤波输出alpha 越大跟随越快越小越平滑。做电机电流采样这种需要快速响应的场景alpha 取 0.3 到 0.5做温度采样alpha 取 0.05 到 0.1。滤波代码放不进 DMA 中断里执行的话就在主循环里批量处理 DMA 缓冲区里的数据。DMA 采集 64 个点主循环里对这 64 个点做一次均值或者中值效果就很好了。还有一种特殊情况数据每过一段时间产生一个固定的跳变比如从 1234 跳到 1300 再跳回来这种大概率是参考电压在跳变滤波解决不了得查电源。5. 把 ADC 读电压做成产品的三个验证手法和离地技巧5.1 验证精度用万用表加标准电阻分压网络写完驱动代码先别急着接真实传感器拿一个精度 1% 的电阻做个分压网络比如 10kΩ 和 10kΩ 从 3.3V 分压理论输出 1.65V。用四位半万用表实测出实际电压值和 ADC 读回来的值换算成电压对比。换算公式是电压 ADC原始值 * 参考电压 / 4095。假设万用表读数是 1.650VADC 读回来是 2046算出来参考电压 1.650 * 4095 / 2046 ≈ 3.302V。如果算出来和 3.3V 差很多说明 VDDA 实际电压不是标称值程序里用的参考电压常数要改成实测值。5.2 用示波器看采样保持波形判断采样时间是否足够有示波器的话在 ADC 引脚并联一个 10kΩ 到地的测试点用方波信号源给 ADC 输入加一个 1kHz 的方波幅值 0 到 3V。连续转换模式下示波器抓到的引脚波形应该是一个个阶梯状信号每个阶梯代表一次采样保持。如果发现阶梯的上沿是圆角说明采样时间不够电容还没充满就开始转换了。这个技巧比拿数据手册算 RC 时间常数直观得多几下就能找到采样时间设置的边界。拿一块 F103 最小系统板做实验跑一段 DMA 连续采样把采样周期参数从 1.5 一路改到 239.5用串口把采集值打出来。你会看到读数从噪声很大的状态慢慢收敛到一个稳定值这个收敛过程就是采样电容的充电过程。这个实验做完你对采样周期这个参数的理解就超过大多数只会抄例程的人。5.3 进阶技巧状态机驱动 ADC轮询和 DMA 共存很多采集系统需要兼顾响应速度和功耗平时 ADC 处于空闲状态有事件来了马上触发一次转换。这种场景可以用定时器触发 中断读取也可以用外部中断触发 ADC 注入通道。F103 的注入通道和规则通道的区别在于注入通道转换优先级高可以打断规则通道的转换序列且有自己的数据寄存器 ADC_JDATA。用注入通道做突发采样的关键是配置JEXTEN和JEXTSEL位选择触发源触发后转换完成产生 JEOC 标志。/* 外部触发使能上升沿触发注入通道 */ ADC1-CR2 | ADC_CR2_JEXTEN_0; /* JEXTEN01上升沿触发 */ ADC1-CR1 | ADC_CR1_JAUTO; /* 自动注入模式规则序列结束后紧跟注入 */ ADC1-CR2 | ADC_CR2_JSWSTART; /* 启动注入转换 */注入通道的好处是不影响规则通道的使用。比如主循环里规则通道在跑 DMA 连续采样外部中断来了就触发一次注入采样结果存在独立寄存器里不会污染 DMA 缓冲区。这是 ADC 模块使用率最高的一种用法很多基于 STM32 的数字电源和电机驱动项目里过流保护信号的采集就是这么做的。本文还有配套的精品资源点击获取