声明
文中内容为观看 BiliBili 视频【STM32入门教程-2023版 细致讲解 中文字幕】后学习并扩展总结。
本文章为个人学习使用,版面观感若有不适请谅解,文中知识仅代表个人观点,若出现错误,欢迎各位批评指正。
一、ADC 模数转换器
1.1 简介
模拟 - 数字转换器(Analog-to-Digital Converter,ADC)是嵌入式系统与集成电路领域中连接模拟电路与数字电路的核心接口器件,其核心功能为将外部引脚输入的连续变化模拟电压信号,量化为数字系统可存储、运算的离散数字变量,是实现模拟信号数字化处理的关键桥梁。
- 核心性能参数(以典型 12 位逐次逼近型 ADC 为例)
逐次逼近型(Successive Approximation Register, SAR)ADC 是嵌入式应用中最常用的架构之一,其核心特性如下:
(1)分辨率与转换精度:12 位分辨率决定了模拟电压的量化粒度,输入电压范围为 0~3.3V 时,转换结果对应数字量范围为 0 ~ 4095(量化步长为 3.3V/4095≈0.806mV);
(2)转换速率:单次转换时间低至 1μs,可满足中高速模拟信号采集需求;
(3)输入通道配置:具备 18 个模拟输入通道,其中 16 个为外部信号采集通道,可对接传感器、模拟电路等外部模拟源,2 个为内部信号源通道(如芯片内部参考电压、温度传感器等)。 - 转换单元架构
为提升信号采集的灵活性与实时性,主流 ADC 模块设计有规则组(Regular Group)和注入组(Injected Group)两个独立转换单元:
(1)规则组:用于常规、批量的模拟信号采集,可预设多通道转换序列,按优先级依次完成指定通道的模数转换;
(2)注入组:具备更高的中断优先级,可打断规则组的转换过程,适用于需要快速响应的紧急模拟信号采集场景(如故障监测、阈值触发)。 - 辅助功能:模拟看门狗
ADC 模块集成的模拟看门狗(Analog Watchdog)功能,可实现对输入模拟电压的实时监测:用户可预设电压上限与下限阈值,当被测通道的模拟电压超出该阈值范围时,ADC 会自动触发中断或事件,无需 CPU 持续轮询,大幅提升系统对异常模拟信号的响应效率。 - 典型器件适配:STM32F103C8T6 的 ADC 资源
STM32F103C8T6 作为主流的 ARM Cortex-M3 内核微控制器,其 ADC 资源配置如下:
(1)硬件模块:集成 ADC1、ADC2 两个独立的 12 位逐次逼近型 ADC;
(2)输入通道:共支持 10 个外部模拟输入通道,覆盖通用 GPIO 引脚的模拟信号采集需求;
(3)兼容特性:继承了规则组 / 注入组转换架构与模拟看门狗功能,转换时间、电压范围等核心参数与上述 12 位 ADC 通用规范一致(0 ~ 3.3V 输入,0 ~ 4095 数字量输出)。
1.2 逐次逼近型ADC
逐次逼近型模数转换器(Successive Approximation ADC, SAR ADC)是一类通过逐次比较实现模拟信号到数字信号转换的经典架构,其核心思想是通过二分查找的方式,逐步逼近输入模拟电压的等效数字值,在转换精度、速度与硬件成本之间实现了良好的折中,因此被广泛应用于中低速数据采集系统。
如图中 ADC0809 为例,其逐次逼近型转换过程可分为以下关键阶段:
(1)通道选择与采样保持 :地址锁存与译码模块(ADDA、ADDB、ADDC 及 ALE 信号)控制通道选择开关,从 8 路模拟输入(IN0~IN7)中选定一路信号,经缓冲后送入比较器输入端。
(2)逐次逼近寄存器(SAR)初始化 :转换启动(START)信号触发后,定时与控制模块初始化 SAR,将其最高位(MSB)置 1,其余位清零,生成首个试探数字量。
(3)DAC 重构与比较 :SAR 输出的数字量送入数模转换器(DAC),重构为对应的模拟参考电压。该电压与输入模拟电压在比较器中进行比较:若输入电压高于 DAC 输出,则 SAR 当前位保持为 1;反之则清零。
(4)迭代逼近 :定时与控制模块驱动 SAR 按位(从次高位至最低位)重复上述置位、比较、修正过程,每一位的确定均基于前一次比较结果,逐步缩小数字量与输入模拟电压的误差范围。
(5)转换完成与输出锁存 :当 SAR 所有位(8 位)均被确定后,转换结束(EOC)信号置位,SAR 中的数字结果被锁存至 8 位三态锁存缓冲器。当输出使能(OE)信号有效时,转换结果(D0~D7)可被外部系统读取。
该架构的核心优势在于:通过 SAR 的逐次迭代,在保证 8 位分辨率的前提下,将转换时间控制在合理范围内;同时,DAC 与比较器的组合实现了高精度的电压比较,而通道选择与三态锁存缓冲器则提升了系统的多通道采集能力与接口兼容性。

1.3 ADC 框图
下图展示了 STM32 系列微控制器中 12 位逐次逼近型模拟 - 数字转换器(ADC)的完整硬件架构,其核心功能是实现模拟信号到数字信号的高精度转换,并通过规则组与注入组双转换单元、硬件触发及中断机制,为复杂数据采集系统提供灵活、高效的信号处理能力。
- (1)模拟前端与通道选择
ADC 的模拟前端由模拟多路开关构成,可通过 GPIO 端口选择最多 16 个外部模拟输入通道(ADCx_IN0 至 ADCx_IN15),同时集成了内部温度传感器与内部参考电压源(VREFINT)作为内部信号源。输入信号的参考电压由外部参考电压引脚 VREF+ 、VREF- 及电源引脚 VDDA 、VSSA 提供,以保证转换精度。模拟多路开关可将选定的输入信号送入模拟至数字转换器核心,支持规则组最多 16 通道序列转换与注入组最多 4 通道序列转换。 - (2)核心转换单元:规则组与注入组
为满足不同优先级的采集需求,ADC 模块设计了两个独立的转换单元:
规则组(Regular Group) :用于常规、周期性的多通道数据采集,可配置 16 个通道的转换序列,转换结果存储于 16 位的规则通道数据寄存器中。规则组的转换可由定时器触发(如 TIM1_CH1、TIM2_CH2 等)、外部中断(EXTI_11)或软件触发启动,转换完成后可触发 DMA 请求,实现数据的高速、无 CPU 干预传输。
注入组(Injected Group):具备更高的优先级,可在规则组转换过程中被打断,用于紧急或高实时性的信号采集(如故障监测)。注入组最多支持 4 个通道的序列转换,结果存储于 4 个独立的 16 位注入通道数据寄存器中,其转换可由专用定时器触发(如 TIM1_TRGO、TIM4_CH4 等)或外部触发(EXTTRIG)启动。 - (3)控制与触发机制
ADC 的转换触发源丰富,可通过 JEXTSEL [2:0] 与 EXTSEL [2:0] 控制位选择不同的触发信号:
注入组可由 TIM1_TRGO、TIM4_CH4、TIM8_CH4 等定时器事件或外部触发(EXTTRIG)启动;
规则组可由 TIM1_CH1、TIM2_CH3、TIM3_CH2 等定时器事件或外部中断(EXTI_11)启动;
同时,软件可直接触发转换,或通过 ADCx_ETRGREQ_REMAP 控制位重映射外部触发信号,提升系统灵活性。 - (4)中断与模拟看门狗
模块集成了完善的中断机制与模拟看门狗功能,以增强系统的异常处理能力:
中断标志位与使能位 :转换结束(EOC)、注入转换结束(JEOC)及模拟看门狗事件(AWD)均可产生独立的中断标志位,通过 EOCIE、JEOCIE、AWDIE 使能位控制中断触发,中断请求最终送至嵌套向量中断控制器(NVIC)进行优先级调度。
模拟看门狗(Analog Watchdog):可通过阈值高限(12 位)与阈值低限(12 位)寄存器设定电压范围,当所选通道的模拟输入电压超出该范围时,自动触发 AWD 中断,实现对关键信号的实时、无 CPU 轮询监测。 - (5)时钟与数据输出
ADC 的工作时钟(ADCCLK)由 ADC 预分频器提供,确保转换速率与精度的平衡。转换完成后,规则组数据可通过 DMA 请求直接传输至内存,注入组数据则存储于专用寄存器中,供 CPU 读取。整个模块通过地址 / 数据总线与微控制器内核交互,支持高效的数据访问与配置。
该架构通过双转换单元、多源触发、中断与 DMA 支持及模拟看门狗功能,构建了一个兼具灵活性、实时性与可靠性的模拟信号采集系统,广泛适用于工业控制、传感器网络及嵌入式测量等应用场景。

1.4 ADC 基本结构
逐次逼近型模拟 - 数字转换器(ADC)的核心架构以多通道信号采集、双优先级转换单元及硬件辅助监测为设计核心,构建了兼具灵活性与实时性的模拟信号数字化处理系统。其模拟前端通过多路选择开关,可接入 16 个来自 GPIO 端口的外部模拟输入通道,同时集成内部温度传感器与内部参考电压源(VREFINT)作为内部信号源,为系统提供多样化的信号采集能力。经选择后的信号进入 AD 转换器核心,该核心划分为规则组与注入组两个独立转换单元:规则组支持最多 16 个通道的序列转换,转换结果存储于单一规则组结果寄存器,适用于常规、周期性的数据采集任务;注入组支持最多 4 个通道的序列转换,结果存储于 4 个独立的注入组结果寄存器,具备更高优先级,可在规则组转换过程中被触发,以满足紧急或高实时性的采集需求。转换的启动由触发控制模块管理,可通过软件、定时器事件或外部中断等多种方式触发,而转换时钟则由复位与时钟控制(RCC)模块提供,以确保转换速率与精度的平衡。转换完成后,EOC(转换结束)信号被置位,同时模拟看门狗模块可对输入电压进行实时监测,当电压超出预设阈值时触发中断,无需 CPU 持续轮询。中断输出控制模块将转换结束、注入转换结束及看门狗事件等中断请求送至嵌套向量中断控制器(NVIC),实现高效的异常处理与任务调度。整个模块通过开关控制与数据寄存器的设计,实现了与微控制器内核的高效交互,为工业控制、传感器网络及嵌入式测量等应用场景提供了可靠的模拟信号采集解决方案。

1.5 ADC 输入通道
下表为 STM32 系列微控制器中 ADC1、ADC2 与 ADC3 模块的通道引脚映射关系,涵盖 16 个外部模拟输入通道及 2 个内部信号源(温度传感器、内部参考电压),各通道对应 GPIO 引脚的复用配置如下:
| 通道 | ADC1 | ADC2 | ADC3 |
|---|---|---|---|
| 通道0 | PA0 | PA0 | PA0 |
| 通道1 | PA1 | PA1 | PA1 |
| 通道2 | PA2 | PA2 | PA2 |
| 通道3 | PA3 | PA3 | PA3 |
| 通道4 | PA4 | PA4 | PF6 |
| 通道5 | PA5 | PA5 | PF7 |
| 通道6 | PA6 | PA6 | PF8 |
| 通道7 | PA7 | PA7 | PF9 |
| 通道8 | PB0 | PB0 | PF10 |
| 通道9 | PB1 | PB1 | |
| 通道10 | PC0 | PC0 | PC0 |
| 通道11 | PC1 | PC1 | PC1 |
| 通道12 | PC2 | PC2 | PC2 |
| 通道13 | PC3 | PC3 | PC3 |
| 通道14 | PC4 | PC4 | |
| 通道15 | PC5 | PC5 | |
| 通道16 | 温度传感器 | ||
| 通道17 | 内部参考电压 |
1.6 转换模式
ADC 模块支持多种转换工作模式,根据转换触发方式与通道处理策略,可分为单次 / 连续转换、扫描 / 非扫描模式的不同组合。不同模式在通道切换机制、转换启停控制及数据更新方式上存在差异,能够适配单通道定点采样、单通道连续监测、多通道批量采集及多通道实时巡检等多样化应用场景,为嵌入式系统模拟信号采集提供灵活可靠的配置方案。
(1)单次转换,非扫描模式
单次转换非扫描模式是 ADC 最基础的工作模式之一,其核心特征为:每次转换仅针对一个预设通道执行单次模数转换,转换完成后模块自动停止。在该模式下,ADC 通过触发信号(软件、定时器或外部事件)启动转换,对指定通道的模拟输入进行一次采样、量化与编码,结果存入对应数据寄存器后,EOC(转换结束)标志位置位,可触发中断或 DMA 请求。此模式适用于对单一模拟信号进行离散采样的场景,如周期性温度采集,其优势在于功耗低、控制逻辑简单,但无法实现多通道序列采集。

(2)连续转换,非扫描模式
连续转换非扫描模式在单次转换的基础上,通过内部控制逻辑实现对单一通道的连续转换。当转换启动后,ADC 会持续对同一通道进行采样与转换,无需再次触发,每次转换完成后自动启动下一次转换,转换结果不断更新至数据寄存器,EOC 标志位在每次转换结束时置位。该模式适用于对单一高频模拟信号进行连续监测的场景,如实时电压监控,可保证信号采集的连续性,但需注意数据寄存器的更新速率与 CPU 或 DMA 读取速率的匹配,避免数据丢失。

(3)单次转换,扫描模式
单次转换扫描模式支持对多通道序列执行单次批量转换。用户可预先配置通道序列(如通道 0 至通道 3),转换启动后,ADC 按预设顺序依次对序列中的每个通道完成一次转换,所有通道转换完成后模块停止工作。转换结果按通道顺序存入规则组或注入组数据寄存器,EOC 或 JEOC(注入转换结束)标志位在序列完成后置位。此模式适用于多通道传感器阵列的周期性批量采集,如环境参数监测系统,可在单次触发下完成多路信号采集,提升系统效率。

(4)连续转换,扫描模式
连续转换扫描模式是扫描模式与连续转换的结合,ADC 在完成一次多通道序列转换后,自动重新启动下一轮相同序列的转换,形成连续的多通道采集循环。该模式下,通道序列按预设顺序重复执行转换,结果不断更新至对应寄存器,EOC 标志位在每轮序列结束后置位,可通过 DMA 实现数据的连续传输。此模式适用于对多通道信号进行长期、连续监测的场景,如工业过程控制中的多参数实时采集,能够在无需频繁触发的情况下,持续获取多路模拟数据,但对系统的数据处理与存储能力要求较高。

1.7 触发控制
下表为 STM32 系列微控制器中 ADC1 与 ADC2 模块规则通道的外部触发源配置表,涵盖来自片上定时器的内部信号、外部引脚事件及软件控制位等多种触发方式,各触发源对应 EXTSEL [2:0] 控制位编码如下:
| 触发源 | 类型 | EXTSEL[2:0] |
|---|---|---|
| TIM1_CC1事件 | 来自片上定时器的内部信号 | 000 |
| TIM1_CC2事件 | 来自片上定时器的内部信号 | 001 |
| TIM1_CC3事件 | 来自片上定时器的内部信号 | 010 |
| TIM2_CC2事件 | 来自片上定时器的内部信号 | 011 |
| TIM3_TRGO事件 | 来自片上定时器的内部信号 | 100 |
| TIM4_CC4事件 | 来自片上定时器的内部信号 | 101 |
| EXTI线11/TIM8_TRGO事件(1)(2) | 外部引脚/来自片上定时器的内部信号 | 110 |
| SWSTART | 软件控制位 | 111 |
1.8 数据对齐
在逐次逼近型 ADC 的数据寄存器中,数据对齐方式是指 12 位转换结果在 16 位寄存器中的存储位置,主要分为左对齐与右对齐两种模式,其选择直接影响数据读取、处理及精度计算的实现方式。
- 数据右对齐(Right Alignment)
数据右对齐是将 12 位转换结果的最低有效位(LSB)与 16 位数据寄存器的最低有效位对齐,结果的高 4 位填充为 0。这种方式下,寄存器中存储的数值与实际转换结果的十进制值直接对应,无需额外移位操作即可进行线性计算,便于直接读取和处理原始量化值。例如,当输入电压对应数字量为 0x0A3 时,右对齐存储为 0x00A3,可直接作为无符号整数参与运算,适用于需要快速进行电压换算、数据统计或与其他数字信号直接比较的场景,是嵌入式系统中最常用的对齐方式。
| 0 | 0 | 0 | 0 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|---|
- 数据左对齐(Left Alignment)
数据左对齐是将 12 位转换结果的最高有效位(MSB)与 16 位数据寄存器的最高有效位对齐,结果的低 4 位填充为 0。这种方式下,寄存器中存储的数值为实际转换结果左移 4 位后的值,例如,当输入电压对应数字量为 0x0A3 时,左对齐存储为 0xA30。左对齐模式的优势在于,当需要对转换结果进行右移操作以降低精度(如简化运算)或与其他高位宽数据进行拼接时,可直接利用寄存器的高位部分,无需额外的位操作,适用于需要快速数据截断、滤波或与 16 位外设直接通信的场景。
| D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 0 | 0 | 0 | 0 |
|---|
两种对齐方式的选择需根据系统的数据处理需求、运算效率及外设接口要求综合考量,右对齐优先保证数据的直接可读性与计算便捷性,左对齐则更适合需要位操作或数据拼接的应用场景。
1.9 转换时间
模拟 - 数字转换(ADC)的核心过程包含采样、保持、量化与编码四个关键阶段:采样阶段通过采样开关对连续变化的模拟电压进行离散化捕获;保持阶段将采样得到的瞬时电压值锁存,为后续处理提供稳定的输入;量化阶段将保持的模拟电压按设定分辨率映射为离散的数字量级;编码阶段则将量化结果转换为数字系统可识别的二进制编码,完成模拟信号到数字信号的最终转换。
STM32 系列 ADC 的总转换时间(TCONV)由采样时间与核心转换时间两部分构成,其计算公式为:
T C O N V = 采样时间 + 12.5 × T A D C T_{CONV} = 采样时间 + 12.5 × T_{ADC} TCONV=采样时间+12.5×TADC
其中,TADC 为单个 ADC 时钟周期,由 ADC 模块的工作时钟(ADCCLK)决定,满足 TADC = 1 / ADCCLK。
以 ADCCLK = 14MHz 为例,单个 ADC 时钟周期 TADC = 1 / 14 MHz ≈ 71.43 ns。若配置采样时间为 1.5 个 ADC 周期,则总转换时间计算如下:
T C O N V = 1.5 × T A D C + 12.5 × T A D C = 14 × T A D C T_{CONV} = 1.5×T_{ADC} + 12.5×T_{ADC} = 14×T_{ADC} TCONV=1.5×TADC+12.5×TADC=14×TADC
代入 TADC 数值可得:TCONV = 14 × (1 / 14 MHz) = 1 μs。
该计算模型表明,STM32 ADC 的转换时间可通过调整 ADCCLK 频率与采样时间灵活配置:采样时间越长,信号采集的稳定性越高,但总转换时间增加;ADCCLK 频率越高,单个 ADC 周期越短,转换速率越快,需在转换精度与速率间实现合理折中。
1.10 ADC 校准功能
ADC 模块集成内置自校准功能,用于消除内部电容器阵列失配、工艺偏差及环境因素引起的静态误差,可显著提升模数转换的整体精度与稳定性。校准过程通过硬件自动完成,其核心原理是对内部各电容单元逐一检测并生成对应的误差修正码,该数字修正码将被固化至校准逻辑中,用于在后续正常转换过程中实时补偿各电容器引入的误差,从而有效抑制由内部电容网络非理想特性造成的偏移误差与增益误差。
为保证校准效果与系统可靠性,建议在上电初始化阶段、电源电压恢复或工作环境发生显著变化后执行一次完整校准。在启动校准操作前,ADC 必须先进入关断状态,并保持该状态不少于两个 ADC 时钟周期,以确保内部模拟电路充分复位、电容节点状态稳定,避免残留电平对校准结果产生干扰。完成一次校准后,模块即可进入正常工作模式,在无需 CPU 干预的情况下实现高精度、低误差的模拟信号数字化转换。
二、AD 单通道 和 AD 多通道的实现
2.1 AD 单通道的实现
-
首先,按下图接线方式,搭建面包板电路连接 OLED 显示屏,并将电位器与 PA0 连接,然后将 DAP-Link / ST-Link 连接到 STM32 最小系统板上,为使 OLED 显示屏的 VCC 和 GND 正确连接正负极,请先连接对应正负极跳线(或直接使用 GPIO 口进行供电)。

-
直接复制先前演示的已有文件目录,重命名并双击后缀名为 .uvprojx 的文件打开工程文件,并对 main.c 进行修改,工程中所使用的全部头文件其详细内容已放于文末。
#include "stm32f10x.h" // Device header
#include <OLED.h>
#include <AD.h>
#include <Delay.h>uint16_t ADValue;
float Voltage;int main(void){
OLED_Init();
AD_Init();OLED_ShowString(1, 1, "ADValue:"); OLED_ShowString(2, 1, "Voltage: 0.00 v"); while(1){ ADValue = AD_GetValue(); Voltage = (float)ADValue / 4095 * 3.3; OLED_ShowNum(1, 10, ADValue, 4); OLED_ShowNum(2, 10, Voltage, 1); OLED_ShowNum(2, 12, (uint16_t)(Voltage * 100) % 100, 2); Delay_ms(100); }}
-
通过十字螺丝刀旋转电位器调节旋钮,可实时观测 OLED 显示屏上电压值(Voltage)与 ADC 转换数值(ADValue)的同步变化。

2.2 AD 多通道的实现
-
首先,按下图接线方式,搭建面包板电路连接 OLED 显示屏,并将电位器、热敏传感器、反射式红外传感器分别与 PA0、PA2、PA4 连接,然后将 DAP-Link / ST-Link 连接到 STM32 最小系统板上,为使 OLED 显示屏的 VCC 和 GND 正确连接正负极,请先连接对应正负极跳线(或直接使用 GPIO 口进行供电)。

-
直接复制先前演示的已有文件目录,重命名并双击后缀名为 .uvprojx 的文件打开工程文件,并对 main.c 进行修改,工程中所使用的全部头文件其详细内容已放于文末。
#include "stm32f10x.h" // Device header
#include <OLED.h>
#include <Mult_AD.h>
#include <Delay.h>uint16_t AD0, AD1, AD2;
float Voltage;int main(void){
OLED_Init();
AD_Init();OLED_ShowString(1, 1, "AD0:"); OLED_ShowString(2, 1, "AD1:"); OLED_ShowString(3, 1, "AD2:"); while(1){ AD0 = AD_GetValue(ADC_Channel_0); AD1 = AD_GetValue(ADC_Channel_2); AD2 = AD_GetValue(ADC_Channel_4); OLED_ShowNum(1, 6, AD0, 4); OLED_ShowNum(2, 6, AD1, 4); OLED_ShowNum(3, 6, AD2, 4); Delay_ms(100); }}
-
通过十字螺丝刀旋转电位器调节旋钮、遮挡反射式红外传感器及用手包覆热敏传感器,均可在 OLED 显示屏上实时观察到电压值(Voltage)与 ADC 转换数值(ADValue)的同步动态变化。

三、演示代码关联的头文件与源文件说明
-
Delay 相关头文件请从 STM32 学习 ------ 个人学习笔记3-1(GPIO 输出) 文末查看,此处不重复展示。
-
OLED 相关头文件请从 STM32 学习 ------ 个人学习笔记4(OLED 显示屏及调试工具) 文末查看,此处不重复展示。
-
AD.c
#include "stm32f10x.h" // Device header
void AD_Init(void){
// 提前声明需要使用的结构体
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;// 开启 RCC 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置 ADCCLK 分频器, ADCCLK = 72MHz / 6 = 12MHz RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 配置 GPIO GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 选择规则组的输入通道, 55.5 cycles ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // 配置 ADC// ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 使用连续转换时使用
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_Init(ADC1, &ADC_InitStructure);// 开启 ADC ADC_Cmd(ADC1, ENABLE); // 校准 ADC ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1) == SET); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1) == SET);// ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 使用连续转换时使用
}uint16_t AD_GetValue(void){
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 使用连续转换时添加注释
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 使用连续转换时添加注释
return ADC_GetConversionValue(ADC1);
} -
AD.h
#include "stm32f10x.h" // Device header
#ifndef __AD_H
#define __AD_Hvoid AD_Init(void);
uint16_t AD_GetValue(void);#endif
-
Mult_AD.c
#include "stm32f10x.h" // Device header
void AD_Init(void){
// 提前声明需要使用的结构体
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;// 开启 RCC 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置 ADCCLK 分频器, ADCCLK = 72MHz / 6 = 12MHz RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 配置 GPIO GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置 ADC ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_Init(ADC1, &ADC_InitStructure); // 开启 ADC ADC_Cmd(ADC1, ENABLE); // 校准 ADC ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1) == SET); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1) == SET);}
uint16_t AD_GetValue(uint8_t ADC_Channel){
// 选择规则组的输入通道, 55.5 cycles
ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); return ADC_GetConversionValue(ADC1);}
-
Mult_AD.h
#include "stm32f10x.h" // Device header
#ifndef __MULT_AD_H
#define __MULT_AD_Hvoid AD_Init(void);
uint16_t AD_GetValue(uint8_t ADC_Channel);#endif
文中部分知识参考:B 站 ------ 江协科技;百度百科