文章目录

一、ADC 简介

1、ADC

ADC(Analog-to-Digital Converter,模数转换器),作用是将连续变化的模拟电压信号转换成离散的数字量,是单片机采集外部传感器数据的核心外设。
单片机只能识别数字信号,所有模拟传感器(电压、温度、湿度、压力、电位器)都必须依靠 ADC 采集。

2、STM32F103 ADC 核心参数

分辨率:12位 ADC,数字范围 0 ~ 4095。
参考电压:默认 3.3V。
电压计算公式:实际电压 = ADC采集值 × 3.3 / 4095。
通道数量:最多10个外部模拟通道。
转换速度:最大1MHz(高速采集)。
供电:模拟电压 VDDA=3.3V,模拟地 VSSA=GND。

3、ADC 核心特点

支持单通道、多通道扫描采集。
支持单次转换、连续转换。
支持 DMA 自动搬运,无需CPU干预。
支持中断、看门狗监测电压阈值。
内置内部温度传感器、内部参考电压通道。

4、ADC 采集对象

外部模拟量:电位器、电池电压、光敏、热敏、压力传感器。
内部模拟量:芯片内部温度、内部1.2V基准电压。

二、ADC转换原理

1、ADC转换原理

AD 转换器(ADC)将模拟量转换为数字量通常要经过4个步骤:采样、保持、量化和编码。
  在这里插入图片描述
采样:即是将一个时间上连续变化的模拟量转换为时间上离散变化的模拟量。
保持:将采样结果存储起来,直到下次采样,这个过程叫做保持。一般采样器和保持电路一起总称为采样保持电路。
量化:将采样电平归化为与之接近的离散数字电平,这个过程叫做量化。
编码:将量化后的结果按照一定数制形式表示就是编码。

1.分辨率

ADC 的分辨率是指对于允许范围内的模拟信号,它能输出离散数字信号值的个数。
这些信号值通常用二进制数来存储,因此分辨率经常用比特作为单位,且这些离散值的个数是2的幂指数。
例如:12位ADC的分辨率就是12位,或者说分辨率为满刻度的1/(2^12)。
一个10V满刻度的12位ADC能分辨输入电压变化最小值是10V×1/(212)=2.4mV。

2.转换误差

转换误差通常是以输出误差的最大值形式给出。
它表示A/D转换器实际输出的数字量和理论上的输出数字量之间的差别。
常用最低有效位的倍数表示。
例如:给出相对误差≤±LSB/2,这就表明实际输出的数字量和理论上应得到的输出数字量之间的误差小于最低位的半个字。

3.转换速率

ADC 的转换速率是能够重复进行数据转换的速度,即每秒转换的次数。
而完成一次A/D转换所需的时间(包括稳定时间),则是转换速率的倒数。

2、主要方法

将采样电平(模拟值)转换为数字值时,主要有两类方法:直接比较型与间接比较型。
直接比较型:就是将输入模拟信号直接与标准的参考电压比较,从而得到数字量。常见的有并行ADC和逐次比较型ADC。
间接比较型:输入模拟量不是直接与参考电压比较,而是将二者变为中间的某种物理量在进行比较,然后将比较所得的结果进行数字编码。常见的有双积分型ADC。

3、逐次逼近型ADC

采用逐次逼近法的AD转换器是有一个比较器、DA转换器、缓冲寄存器(比较寄存器)和控制逻辑电路组成。
  在这里插入图片描述

原理:
   从高位到低位逐次试探比较,就像用天平秤物体,从重到轻逐级增减砝码进行试探。
过程:
   1)通过置数选择寄存器置SRA最高位"1",其余为"0",经过AD转换成模拟电压Uo。与输入模拟电压Ui比较:
     若Ui >=Uo,保留最高位"1"。
     若Ui < Uo,置最高位"0"。
   2)次高位"1",其余"0",重复以上过程,直到确定SAR的最低位应取"1"或"0"为止。
   3)此时,SAR的内容就是对应输入模拟电压转换后的数字量。

4、双积分型ADC

采用双积分法的AD转换器由电子开关、积分器、比较器和控制逻辑等部件组成。
  在这里插入图片描述

原理:
  将输入电压变换成与其平均值成正比的时间间隔,再把此时间隔转换成数字量,属于间接转换。
过程:
  先将开关接通待转换的模拟量Vi,Vi采样输入到积分器,积分器从零开始进行固定时间T的正向积分,时间T到后,开关再接通与Vi极性相反的基准电压Vref,将Vref输入到积分器,进行反向积分,直到输出为0V时停止积分。
  Vi越大,积分器输出电压越大,反向积分时间也越长。
  计数器在反向积分时间内所计的数值,就是输入模拟电压Vi所对应的数字量,实现了AD转换。

三、STM32F103-ADC

1、ADC功能框图

  在这里插入图片描述

2、框图解析

1️⃣ 模拟电源参考区(标号 1)

引脚定义:
  VREF+:高精度参考电压输入(可选外接 2.5V 基准)。
  VREF-:参考地,内部与VSSA短接。
  VDDA:模拟电源 3.3V,VSSA模拟地。
作用:为 ADC 模拟电路提供纯净电源与电压标尺,决定采样量程 0~VREF。
硬件要点:VDDA 必须单独加 0.1μF 滤波电容,数字地与模拟地单点共地,减少噪声干扰。

2️⃣ 模拟输入通道区(标号 2)

外部通道:ADCx_IN0~IN15,共 16 路 GPIO 模拟输入。
内部专属通道:片内温度传感器、内部参考电压VREFINT。
输入特性:单极性 0~3.3V,无负压测量能力;高内阻传感器需 RC 滤波 / 运放缓冲。

3️⃣ 多路模拟开关 & 双通道组(标号 3)

ADC 分为两组独立转换序列:
  规则通道(Regular):最多 16 个通道,日常采集主序列,转换结果存 16 位寄存器,支持 DMA 搬运。
  注入通道(Injected):最多 4 个通道,高优先级抢占,可打断规则通道转换;结果独立 4×16 位寄存器,无 DMA。
多路开关作用:分时切换多路模拟输入,送入 ADC 转换器核心。

4️⃣ 外部触发源选择区(标号 4)

控制规则组 / 注入组启动转换的触发信号,分为 3 大类:
  定时器内部触发:TIM1~TIM8 TRGO/CH 通道事件(定时周期性采样常用)。
  外部中断 EXTI:EXTI11/EXTI15 引脚电平边沿触发。
  软件触发:寄存器置位手动启动转换。
控制寄存器位:EXTSEL[2:0](规则)、JEXTSEL[2:0](注入),支持重映射引脚ETRGREMAP。
应用场景:电机采样用 TIM 触发、按键采集用 EXTI 触发。

5️⃣ ADC 时钟预分频(标号 5 ADCCLK)

ADC 内核时钟来源:APB2 时钟分频(最大允许 14MHz)。
分频配置:2/4/6/8 分频,时钟过快会降低采样精度,噪声增大。

6️⃣ 数据存储与 DMA 请求(标号 6)

规则数据寄存器:16 位,每次转换完成产生DMA 请求,可自动搬运数据到内存,释放 CPU。
注入数据寄存器:4 个独立 16 位寄存器,无 DMA,需 CPU 主动读取。
数据对齐:可配置左对齐 / 右对齐(12 位结果默认右对齐,数值直接计算电压)。

7️⃣ 中断与模拟看门狗 AWD(标号 7)

中断标志(输出至 NVIC)
  EOC:规则通道转换完成。
  JEOC:注入通道转换完成。
  AWD:模拟看门狗阈值超限事件。
  每个标志对应独立中断使能位(EOCIE/JEOCIE/AWDIE)。
模拟看门狗 AWD 核心功能:
  内置 12 位高低阈值寄存器(高限 / 低限)。
  实时对比 ADC 采样值与阈值,超出范围立即触发 AWD 中断。
  用途:电池低压告警、传感器超限保护(和 PVD 硬件电压检测互补,AWD 是软件 ADC 采样判断)。

3、ADC 工作原理

模拟电压 → 采样保持电路 → 逐次逼近寄存器(SAR) → 数字量输出 → 存入数据寄存器 → CPU/DMA读取
STM32 ADC 采用逐次逼近型模数转换,精度高、速度快、稳定性好。

4、三种转换模式

1)单次转换模式

触发一次,转换一次,结束后停止。适合低频、偶尔采集的场景,节省功耗。

2)连续转换模式

启动后不停重复转换,持续刷新数据,适合实时监测电压。

3)扫描模式(多通道)

自动依次扫描多个通道,配合DMA可实现多通道全自动采集。

5、触发方式

软件触发:代码直接启动转换(最常用)。
定时器触发:定时精准采样,用于波形采集。

6、采样时间

ADC 需要一定时间采集稳定电压,采样时间越长,数据越稳定、速度越慢。工程常用:55.5个周期(平衡速度与精度)。

7、F103 ADC 通道引脚

  在这里插入图片描述

所有ADC通道引脚必须配置为模拟输入模式。

四、ADC编程模块

1、ADC 硬件整体结构

模拟输入引脚 → 采样保持电路 → 多路选择开关 → AD转换器 → 数据寄存器 → DMA/CPU读取 → 中断控制器。

2、ADC 结构体

1.ADC句柄结构体

		typedef struct
		{
		  ADC_TypeDef        *Instance;      // ADC寄存器基地址:ADC1/ADC2/ADC3
		  ADC_InitTypeDef    Init;           // ADC全局初始化参数
		  DMA_HandleTypeDef  *DMA_Handle;    // 绑定DMA句柄(规则通道DMA传输)
		  HAL_LockTypeDef    Lock;           // 互斥锁,防止多任务并发操作冲突
		  __IO uint32_t      State;          // ADC运行状态:就绪/转换中/错误
		  __IO uint32_t      ErrorCode;      // 错误标志:溢出、DMA错误、硬件故障
		  uint8_t            NbrOfCurrentConversionRank; // 当前扫描序列序号
		} ADC_HandleTypeDef;

2.ADC初始化结构体

		typedef struct
		{
		  uint32_t ADC_Mode;                    // ADC工作模式:独立/双ADC同步
		  FunctionalState ADC_ScanConvMode;     // 扫描模式:ENABLE多通道 / DISABLE单通道
		  FunctionalState ADC_ContinuousConvMode;// 连续转换:ENABLE循环采集 / DISABLE单次
		  uint32_t ADC_ExternalTrigConv;        // 规则通道外部触发源(框图4所有TIM/EXTI)
		  uint32_t ADC_DataAlign;               // 数据对齐:右对齐/左对齐
		  uint8_t ADC_NbrOfChannel;             // 规则序列总通道数量(最多16)
		} ADC_InitTypeDef;

3.单通道配置结构体

		typedef struct
		{
		  uint32_t ADC_Channel;         // 通道号:IN0~IN15、内部温度传感器、VREFINT
		  uint32_t ADC_SamplingTime;    // 通道采样保持时间(电容充电时长,抗干扰)
		  uint32_t ADC_Rank;            // 序列排序Rank:1~16,扫描顺序
		} ADC_ChannelConfTypeDef;

4.模拟看门狗结构体

		typedef struct
		{
		  uint32_t WatchdogMode;    // 看门狗模式:单通道/全通道监测
		  uint32_t Channel;         // 需要监控的通道号
		  uint16_t HighThreshold;   // 12位上限阈值(0~4095)
		  uint16_t LowThreshold;    // 12位下限阈值(0~4095)
		  FunctionalState ITMode;   // ENABLE开启AWD中断
		} ADC_AnalogWDGConfTypeDef;

5. 注入通道配套结构体

		typedef struct
		{
		  uint32_t ExternalTrigInjecConv; // 注入通道专用外部触发
		  uint8_t NbrOfInjecChannel;      // 注入通道数量(1~4)
		  FunctionalState AutoInjec;      // 规则转换完成自动触发注入转换
		} ADC_InjectionConfigTypeDef;

3、HAL_API

1.初始化与反初始化

外设初始化:
  HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc);
  功能:根据hadc->Init结构体配置 ADC 全局模式、扫描、连续转换、触发、通道总数。
  配套:MX_ADCx_Init()自动生成函数。
注销外设:
  HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc);
  功能:关闭 ADC 时钟、复位寄存器、释放锁资源。
单通道配置(规则通道):
  HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc, ADC_ChannelConfTypeDef *sConfig);
  功能:配置规则组单通道:通道号、采样时间、扫描序列 Rank。

2.转换控制

单次转换(阻塞式,等待转换完成)
  HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc);
  HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout);
  uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc);
  HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *hadc);
  流程:启动→轮询标志→读取数据→停止,无中断无 DMA。
单次转换(中断非阻塞)
  HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc);
  HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef *hadc);
  转换完成触发HAL_ADC_ConvCpltCallback。
DMA 循环采集(最常用多通道)
  HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length);
  HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef *hadc);
  自动搬运采样值到内存,支持DMA_CIRCULAR持续采集;
  回调:半满ConvHalfCpltCallback、全满ConvCpltCallback。

3.注入通道

注入组全局配置:
  HAL_StatusTypeDef HAL_ADCEx_InjectedConfig(ADC_HandleTypeDef *hadc, ADC_InjectionConfigTypeDef *sInjConfig);
  功能:设置注入触发源、通道数量、AutoInjec 自动注入使能。
单注入通道配置:
  HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef *hadc, ADC_InjectionChannelConfTypeDef *sConfig);
  功能:配置注入通道、采样时间、InjectedRank、偏移校正值。
注入通道启动 / 停止:
  阻塞轮询:
  HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef *hadc);
  HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout);
  HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef *hadc);
  中断触发(JEOC 转换完成中断):
  HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef *hadc);
  HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef *hadc);
读取注入通道采样值:
  uint16_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef *hadc, uint32_t InjectedRank);
  参数:ADC_INJECTED_RANK_1 ~ ADC_INJECTED_RANK_4,无 DMA,必须 CPU 读取。
注入通道偏移校正
  HAL_StatusTypeDef HAL_ADCEx_SetInjectedOffset(ADC_HandleTypeDef *hadc, uint32_t InjectedRank, uint16_t Offset);
  转换结果 = 原始采样值 - Offset,用于双极性信号零点校正。

4.模拟看门狗

配置监控通道、高低阈值、中断使能;
  HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef *hadc, ADC_AnalogWDGConfTypeDef *sAnalogWDGConfig);
回调函数:
  void HAL_ADC_LevelOutOfWindowCallback (ADC_HandleTypeDef * hadc) 。

5.中断控制

使能 / 关闭 ADC 中断:
  __HAL_ADC_ENABLE_IT
  __HAL_ADC_DISABLE_IT
查询中断状态:
  __HAL_ADC_GET_IT_SOURCE
ADC 中断服务入口(放在 stm32f1xx_it.c)

				void ADC_2_IRQHandler(void)
				{
				  HAL_ADC_IRQHandler(&hadc1);
				}
				//HAL_ADC_IRQHandler自动分发到对应回调函数。

6.回调函数

规则通道通用回调:
  // 单次转换完成(非DMA)
  void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);
  // DMA缓冲区半满
  void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc);
  // ADC溢出错误
  void HAL_ADC_ErrorCallback(ADC_HandleTypeDef hadc);
注入通道专用回调:
  void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef
hadc);
模拟看门狗超限回调:
  void HAL_ADC_LevelOutOfWindowCallback (ADC_HandleTypeDef * hadc) ;

7.状态及错误查询

获取 ADC 运行状态:
  uint32_t HAL_ADC_GetState(ADC_HandleTypeDef *hadc);
  状态宏:
  HAL_ADC_STATE_READY:空闲就绪。
  HAL_ADC_STATE_BUSY:规则转换中。
  HAL_ADC_STATE_BUSY_INJ:注入抢占转换中。
  HAL_ADC_STATE_ERROR:故障。
获取错误码
  uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc);
  错误宏:
  HAL_ADC_ERROR_NONE:无错误。
  HAL_ADC_ERROR_OVR:数据溢出。
  HAL_ADC_ERROR_DMA:DMA 传输故障。
  HAL_ADC_ERROR_INTERNAL:硬件内部故障。
硬件校准:
  HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc);
  使用流程:ADC 上电后先执行校准,再启动转换,消除内部偏移误差。

8.内部温度参考电压

开启内部通道时钟:__HAL_RCC_ADC_TEMP_VREFINT_ENABLE()
通道选择:
  ADC_CHANNEL_TEMPSENSOR 片内温度
  ADC_CHANNEL_VREFINT 1.2V 内部基准(用于校正 3.3V 参考电压)
读取方式同普通规则通道,调用HAL_ADC_GetValue()获取原始值后换算。

五、ADC 应用实例

1、单通道连续采集

1.CubeMX配置

进入芯片引脚视图,选中对应通道引脚,设置为 ADCx_INy
例:PC1 → ADC1_IN11
系统配置 → RCC:开启 HSE/HIS,APB2 时钟保证 ADC 时钟≤14MHz
系统配置 → NVIC:如需中断读取,开启 ADC 全局中断;查询方式可不开 ADC 参数配置(Parameter Settings):
    在这里插入图片描述

配置项 当前值 含义** & **问题
Scan Conversion Mode Disabled 单通道模式,无法多路采集,必须开启才能多通道 DMA
Continuous Conversion Mode Enabled 连续转换(符合全自动采集需求,保留)
Number Of Conversion 1 仅 1 路通道,多通道需改成对应通道总数
External Trigger Source Software 软件触发,上电启动自动循环
Rank1 Channel Channel11 当前仅采集 IN11
Sampling Time 1.5 Cycles 适合低内阻信号;NTC / 分压电阻建议改成 239.5 Cycles
Injected Conversions Disable 注入通道关闭(不影响规则 DMA 方案)
Analog WatchDog Mode 未勾选 模拟看门狗关闭,需要手动开启并配置阈值

2.实例代码

		#include "stdio.h"
		#define V_REF 3.3f
		#define ADC_MAX 4096.0f
		/* 重定向printf */
		#ifdef __GNUC__
		#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
		#else
		#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
		#endif
		PUTCHAR_PROTOTYPE
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
			return ch;
		}
		
		uint16_t adc_read_single(void)
		{
		  uint16_t adc_val = 0;
		  // 启动单次转换
		  HAL_ADC_Start(&hadc1);
		  // 等待转换完成,超时10ms
		  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
		  {
		    adc_val = HAL_ADC_GetValue(&hadc1);
		  }
		  // 停止ADC外设
		  HAL_ADC_Stop(&hadc1);
		  return adc_val;
		}
		
		// 使用示例
		int main(void)
		{
		  HAL_Init();
		  SystemClock_Config();
		  MX_GPIO_Init();
		  MX_ADC1_Init();
		
		  while(1)
		  {
		    uint16_t raw = adc_read_single();
		    float voltage = raw * V_REF / ADC_MAX;
			printf("The current AD value = %f V \r\n",voltage);
		    HAL_Delay(500);
		  }
		}

3.实例结果

  在这里插入图片描述

2、多通道(规则通道+片电压+片内温度)DMA+模拟看门狗全自动采集

1.CubeMX 配置

引脚与内部通道开启:

进入芯片引脚视图,选中对应通道引脚,设置为 ADCx_Iny
例:PC1 → ADC1_IN11
  在这里插入图片描述

参数项 设置值 说明
Scan Conversion Mode Enabled 多通道扫描,DMA 多路采集必备
Continuous Conversion Mode Enabled 连续转换,一次启动永久循环采集
Discontinuous Conversion Mode Disabled 关闭间断模式,完整跑完所有 Rank
Data Alignment Right alignment 右对齐,电压计算直观
Number Of Conversion 3 一共 3 路:IN11 / VREFINT / 温度传感器
External Trigger Conversion Source Regular Conversion launched by software 软件触发,上电自动循环
配置 3 路采集序列 Rank(关键:外部 + 两路内部)

在Rank分组依次添加 3 条序列:
Rank 1
  Channel:Channel 11(外部 IN11)。
  Sampling Time:239.5 Cycles(外部分压 / NTC 高阻通用)。
Rank 2
  Channel:Internal reference voltage channel (VREFINT)(内部 1.2V 基准)。
  Sampling Time:239.5 Cycles(内部通道建议长采样保证精度)。
Rank 3
  Channel:Temperature sensor channel(片内温度传感器)。
  Sampling Time:239.5 Cycles(温度传感器必须长采样,手册要求≥10us)。

DMA Settings 配置(全自动循环搬运)

切换顶部 DMA Settings → Add DMA Request → 选择 ADC1 Regular。
DMA 通道参数:
  Mode:Circular 循环模式(自动刷新缓存,无需 CPU 干预)。
  Direction:Peripheral To Memory。
  Peripheral Increment Address:Disable。
  Memory Increment Address:Enable。
  Data Width:Half Word(ADC 输出 16 位数据)。
  Priority:Medium。

WatchDog 模拟看门狗配置(监测外部 IN11)

页面下拉找到WatchDog分组:
  Enable Analog WatchDog Mode ✅勾选开启。
  Watchdog Mode:Single channel regular 仅监控单路规则通道。
  Channel:Channel 11(监控外部输入 IN11 电压)。
  High Threshold:自定义上限(例 2.8V → 2.8/3.34096≈3486)。
  Low Threshold:自定义下限(例 0.4V → 0.4/3.3
4096≈496)。
  Analog WatchDog Interrupt:✅勾选,超限自动触发中断。

NVIC 中断配置

切换NVIC Settings标签:
  勾选 ADC1 global interrupt(AWD 看门狗中断依赖)。
  勾选 ADC 对应 DMA 通道中断(可选,用于缓冲区半满 / 全满回调)。

2.实例代码

		#include "main.h"
		#include "adc.h"
		#include "dma.h"
		#include "stdio.h"
		
		/* 重定向printf */
		#ifdef __GNUC__
		#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
		#else
		#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
		#endif
		PUTCHAR_PROTOTYPE
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
			return ch;
		}
		
		
		// 3路缓存:[0]=IN11  [1]=VREFINT  [2]=片内温度原始值
		#define ADC_CH_NUM 3
		uint16_t adc_buf[ADC_CH_NUM] = {0};
		
		// 电压参数
		#define V_REF_EXTERNAL 3.3f
		#define ADC_FULL_SCALE 4096.0f
		#define VREFINT_STD 1.20f // 内部基准标准1.2V
		
		//AWD 模拟看门狗超限中断(IN11 超出阈值自动触发)
		void HAL_ADC_AnalogWDGCallback(ADC_HandleTypeDef *hadc)
		{
		  if(hadc->Instance == ADC1)
		  {
		
		  }
		}
		//DMA 缓冲区完成回调
		void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
		{
		  if(hadc->Instance == ADC1)
		  {
		  }
		}
		
		int main(void)
		{
		  HAL_Init();
		  SystemClock_Config();
		  MX_DMA_Init();
		  MX_ADC1_Init();
		
		  // 单次启动,全程全自动循环采集,DMA自动刷新数组
		  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, ADC_CH_NUM);
		
		  while (1)
		  {
		    // 1. 外部IN11电压
		    float vol_in11 = adc_buf[0] * V_REF_EXTERNAL / ADC_FULL_SCALE;
		
		    // 2. 实际VDDA供电电压(用内部1.2V基准校准真实电源)
		    float vdda_real = VREFINT_STD * ADC_FULL_SCALE / adc_buf[1];
		
		    // 3. 片内温度计算    
		    uint16_t temp_raw = adc_buf[2];
		     //计算温度电压
		    float temp_v = (float)temp_raw * V_REF_EXTERNAL / ADC_FULL_SCALE;
		    //转换为温度
		    float temp_c = ((1.43-temp_v) / 0.0043f) + 25.0f;
		
		    // 业务逻辑:打印/判断电压温度
		    printf("vol_in11 = %f V,vdda_real = %f V,temp_v = %f V ,temp_c = %f C",vol_in11,vdda_real,temp_v,temp_c);
		    HAL_Delay(200);
		  }
		}

3.实例结果

  在这里插入图片描述

六、ADC 核心要点与避坑大全

1、必考核心知识点

ADC 12位分辨率,数值范围 0~4095,对应电压 0~3.3V。
公式:电压 = ADC值 × 3.3 / 4095。
单通道用单次模式,多通道必须开扫描模式Scan。
工程最优方案:ADC+DMA循环采集,零CPU占用。
ADC引脚必须配置为模拟输入模式。

2、高频坑点

引脚模式错误:设为浮空/上拉导致采样不准。
多通道未开Scan模式,只有第一个通道有数据。
未开连续模式,采集一次就停止。
缓冲区定义为局部变量,DMA采集异常死机。
采样时间过短,数据跳动大、不稳定。
模拟电源不干净,电压波动导致采样漂移。

3、数据滤波优化技巧

多次采样取平均值。
中值滤波、滑动平均滤波。
硬件并联104电容滤波。

4、工程万能搭配方案

单电压采集:单次转换 + 软件延时采集。
多路传感器采集:Scan+Continuous+DMA循环。
高精度采集:加长采样时间+软件滤波。

5、一句话总结

ADC是STM32模数转换外设,12位分辨率将03.3V模拟电压转为04095数字量,支持单通道/多通道、单次/连续转换,配合DMA可实现全自动无CPU采集,是模拟传感器数据采集的核心外设。

七、全篇总结

ADC 是嵌入式模拟信号采集的基石外设,所有传感器、电压检测、信号采集项目都离不开ADC。
掌握CubeMX配置、电压换算公式、DMA全自动采集、软件滤波,即可完成所有智能检测、仪器测量、毕业设计的模拟采集功能。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐