9.STM32H743 ADC
ADC(Analog-to-Digital Converter,模数转换器)是STM32H743处理模拟信号的核心外设,能将传感器(如温湿度、电压、电流)输出的模拟电压转换为数字值,广泛应用于工业测控、消费电子等场景。STM32H743的ADC外设性能远超入门级STM32(如F1/F4)。
这是一个采集器的框架:

一、STM32H743 ADC 核心硬件特性
STM32H743内置3个独立的ADC控制器(ADC1/ADC2/ADC3),支持多通道、高精度、高速采样,核心特性如下:
|
特性 |
说明 |
|
分辨率 |
16位、12位(默认)、10位、8位、6位(分辨率越低,采样速度越快) |
|
采样速率 |
最高3.6MSPS(12位分辨率下),支持批量采样模式 |
|
通道数量 |
每个ADC有16个外部通道(PA0PA7、PB0PB1等)+ 内部通道(温度传感器、参考电压、VBAT) |
|
采样模式 |
单次采样、连续采样、扫描模式(多通道自动轮询)、间断模式 |
|
触发源 |
软件触发(手动启动)、硬件触发(TIM定时器、EXTI外部中断、DMA请求等) |
|
数据对齐 |
右对齐(默认,新手推荐)、左对齐 |
|
转换模式 |
单转换、连续转换、多通道序列转换(支持规则通道/注入通道) |
|
DMA支持 |
支持DMA自动读取转换结果(解放CPU,批量采样必备) |
|
中断支持 |
转换完成、转换过半、注入转换完成、溢出错误等中断 |
|
电压范围 |
模拟输入电压范围:0---3.3V(需外部分压/放大适配非03.3V信号) |
|
校准功能 |
内置自校准(消除偏移误差,提升精度) |
|
双ADC模式 |
支持ADC1/ADC2/ADC3同步采样(如差分信号采集) |
ADC 通道映射
STM32H743的ADC外部通道对应固定GPIO引脚,核心映射示例(以ADC1为例):
|
ADC1通道 |
引脚 |
备注 |
|
CH0 |
PA0 |
常用模拟输入引脚 |
|
CH1 |
PA1 |
|
|
CH2 |
PA2 |
|
|
CH3 |
PA3 |
|
|
CH4 |
PA4 |
|
|
CH5 |
PA5 |
|
|
CH6 |
PA6 |
|
|
CH7 |
PA7 |
|
|
CH8 |
PB0 |
|
|
CH9 |
PB1 |
|
|
CH10~15 |
PC0~PC5 |
部分型号需复用配置 |
内部通道说明
|
内部通道 |
用途 |
转换值计算(参考) |
|
温度传感器 |
测量芯片内部温度 |
温度(℃) = (V_sense - V25)/Avg_Slope + 25 |
|
VREFINT(参考电压) |
校准ADC精度、测量电源电压 |
VREFINT实际值(约1.21V)/转换值 × ADC结果 |
|
VBAT(电池电压) |
测量VBAT引脚电压 |
转换值 × 3.3/4096 × 2(内置1/2分压) |
二、ADC 核心概念
1. 规则通道 vs 注入通道
- 规则通道(Regular Channel):常规采样通道,最多16个,支持序列扫描(如轮询采集CH0~CH3);
- 注入通道(Injected Channel):“紧急”采样通道,最多4个,可打断规则通道采样(如故障检测);
优先掌握规则通道,注入通道仅在特殊场景使用。
2. 采样时间
ADC采样需要一定时间(采样时钟周期数),采样时间越长,精度越高,但速度越慢:
- 采样时间配置范围:1.5~61.5个ADC时钟周期(H743 ADC时钟最大为72MHz);
- 推荐配置:低速信号(如温度传感器)用23.5/47.5周期,高速信号(如音频)用1.5/7.5周期。
3. 转换流程(以12位右对齐为例)
- ADC校准 → 配置通道/采样时间 → 启动转换;
- 对指定通道的模拟电压采样,转换为数字值(0~4095);
- 转换结果存储到数据寄存器(ADC_DR);
- 触发中断/DMA,CPU读取结果(或DMA自动搬运);
- 数字值对应电压:
V = 转换值 × 3.3 / 4096(如转换值2048 → 1.65V)。
三、STM32H743 ADC 配置步骤(HAL库+CubeMX)
推荐用STM32CubeMX可视化配置,结合HAL库编程,以ADC1_CH0(PA0)单次采样+阻塞读取为例,步骤如下:
步骤1:硬件准备
- 开发板:STM32H743核心板;
- 模拟信号:PA0引脚接可调电压源(0~3.3V),或直接接3.3V/GND测试;
- 注意:ADC引脚需配置为模拟输入模式(无上拉/下拉)。
步骤2:CubeMX 配置
- 开启ADC1外设:
-
- 进入“Analog → ADC1”,勾选“ADC1 Enable”;
- 分辨率:12 Bits(默认);
- 数据对齐:Right Alignment(右对齐);
- 扫描模式:Disabled(单次通道无需扫描);
- 连续转换:Disabled(单次采样);
- 触发源:Software Trigger(软件触发)。
- 配置通道参数:
-
- 点击“ADC1_IN0”(对应PA0),设置“Sampling Time”为23.5 Cycles;
- 规则通道序列:Sequence Length = 1,Rank 1 = ADC1_IN0。
- 配置引脚:
-
- PA0 → Analog Input(模拟输入模式,无复用功能);
- 无需上拉/下拉(模拟引脚默认无)。
- 时钟配置:
-
- ADC时钟源:PCLK2(H743 PCLK2最大为72MHz);
- ADC预分频器:默认(确保ADC时钟≤72MHz)。
- 生成代码:选择HAL库,生成MDK/STM32CubeIDE工程。
步骤3:HAL库核心API
|
函数 |
功能 |
|
HAL_ADC_Init() |
初始化ADC外设(CubeMX自动生成) |
|
HAL_ADC_Calibrate() |
ADC自校准(提升精度,建议每次启动后执行) |
|
HAL_ADC_Start() |
启动ADC转换(阻塞式,等待转换完成) |
|
HAL_ADC_PollForConversion() |
轮询等待转换完成(配合HAL_ADC_Start使用) |
|
HAL_ADC_GetValue() |
读取ADC转换结果(数字值) |
|
HAL_ADC_Start_IT() |
启动ADC转换(中断式,非阻塞) |
|
HAL_ADC_Start_DMA() |
启动ADC转换(DMA式,批量采样) |
|
HAL_ADC_IRQHandler() |
ADC中断服务函数(需在stm32h7xx_it.c中实现) |
|
HAL_ADC_ConvCpltCallback() |
ADC转换完成回调函数(中断/DMA) |
|
HAL_ADC_GetError() |
获取ADC错误码(排查转换失败问题) |
四、实战代码示例
示例1:单次采样(阻塞式,读取PA0电压)
#include "stm32h7xx_hal.h"
/* ADC句柄(CubeMX自动生成) */
ADC_HandleTypeDef hadc1;
/* 错误处理函数 */
void Error_Handler(void)
{
while(1)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // LED闪烁表示错误
HAL_Delay(500);
}
}
/**
* @brief 初始化ADC并执行自校准
* @retval HAL_OK: 成功
*/
HAL_StatusTypeDef ADC_Init_Calibrate(void)
{
// 1. ADC初始化
if(HAL_ADC_Init(&hadc1) != HAL_OK)
{
return HAL_ERROR;
}
// 2. ADC自校准(关键:提升精度)
if(HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
/**
* @brief 读取ADC单次转换值并计算电压
* @retval 电压值(单位:mV)
*/
uint16_t ADC_Read_Voltage(void)
{
uint32_t adc_value = 0;
uint16_t voltage_mv = 0;
// 1. 启动ADC转换
HAL_ADC_Start(&hadc1);
// 2. 轮询等待转换完成(超时时间100ms)
if(HAL_ADC_PollForConversion(&hadc1, 100) != HAL_OK)
{
Error_Handler();
}
// 3. 读取转换值(12位右对齐,范围0~4095)
adc_value = HAL_ADC_GetValue(&hadc1);
// 4. 计算电压(mV):V = adc_value * 3300 / 4096
voltage_mv = (uint16_t)(adc_value * 3300 / 4096);
// 5. 停止ADC转换
HAL_ADC_Stop(&hadc1);
return voltage_mv;
}
int main(void)
{
/* 初始化HAL库、系统时钟、ADC、GPIO(LED) */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
// ADC初始化并校准
if(ADC_Init_Calibrate() != HAL_OK)
{
Error_Handler();
}
uint16_t voltage = 0;
while (1)
{
// 读取PA0电压(每1秒读取一次)
voltage = ADC_Read_Voltage();
// 调试输出(可通过串口打印,如:printf("PA0 Voltage: %d mV\r\n", voltage);)
HAL_Delay(1000);
}
}
示例2:多通道扫描+DMA(批量采样CH0~CH3)
适合需要同时采集多个模拟信号的场景(如温湿度、光照、电压),解放CPU:
/* DMA句柄(CubeMX配置ADC1_DMA,如DMA1_Channel1) */
DMA_HandleTypeDef hdma_adc1;
/* 存储4个通道的转换结果(CH0~CH3) */
uint32_t adc_dma_buf[4] = {0};
/**
* @brief 初始化ADC+DMA,启动连续扫描
*/
void ADC_DMA_Init(void)
{
// 1. ADC初始化+校准
ADC_Init_Calibrate();
// 2. 配置ADC规则通道序列(CH0~CH3,长度4)
ADC_ChannelConfTypeDef sConfig = {0};
// Rank1: CH0
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_23CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
// Rank2: CH1
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
// Rank3: CH2
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_3;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
// Rank4: CH3
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_4;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
// 3. 开启ADC连续转换模式
hadc1.Init.ContinuousConvMode = ENABLE;
// 4. 启动ADC DMA转换(循环模式,持续采样)
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_dma_buf, 4);
}
/* ADC1 DMA中断服务函数(stm32h7xx_it.c) */
void DMA1_Channel1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc1);
}
/* ADC DMA转换完成回调函数(每次完成4个通道采样触发) */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
// 处理转换结果(如计算每个通道的电压)
uint16_t ch0_volt = adc_dma_buf[0] * 3300 / 4096;
uint16_t ch1_volt = adc_dma_buf[1] * 3300 / 4096;
uint16_t ch2_volt = adc_dma_buf[2] * 3300 / 4096;
uint16_t ch3_volt = adc_dma_buf[3] * 3300 / 4096;
// 调试输出或数据处理
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}
}
// 主函数中调用
// int main(void)
// {
// HAL_Init();
// SystemClock_Config();
// MX_GPIO_Init();
// MX_ADC1_Init();
// MX_DMA_Init(); // 初始化DMA
//
// ADC_DMA_Init(); // 启动ADC DMA采样
//
// while (1)
// {
// // CPU可处理其他任务(如串口上报、逻辑控制)
// }
// }
五、常见问题与避坑指南
1. 转换值错误/精度低
- 原因1:未执行ADC校准:每次上电/复位后必须执行自校准,否则偏移误差大;
- 原因2:采样时间过短:低速模拟信号(如温度传感器)需足够采样时间(≥15Cycles);
- 原因3:引脚配置错误:ADC引脚未设为“Analog Input”,或误配成数字模式/上拉下拉;
- 原因4:电源噪声:模拟电源(VDD_A)需滤波(外接100nF电容),避免数字电路干扰;
- 排查技巧:将ADC引脚接3.3V,理想转换值应为4095;接GND应为0,验证硬件是否正常。
2. DMA模式采样失败
- DMA通道映射错误:需查手册确认ADC对应的DMA通道(如ADC1→DMA1_Channel1);
- DMA地址配置错误:ADC数据寄存器地址(&hadc1.Instance->DR)、缓冲区地址需正确;
- 未开启DMA中断:NVIC未使能DMA中断,导致回调函数不执行;
- 缓冲区长度不匹配:DMA传输长度需与ADC通道数一致。
3. 多通道扫描顺序错误
- 规则通道的Rank值需与采样顺序一致(Rank1=第一个采样通道,Rank2=第二个);
- 扫描模式未开启(ContinuousConvMode=ENABLE,ScanConvMode=ENABLE)。
4. 电压计算错误
- 右对齐vs左对齐:12位右对齐转换值范围04095,左对齐为065535(需调整计算公式);
- 参考电压错误:H743 ADC参考电压为3.3V(VREF+),若外部接其他参考电压需修改公式。
5. 硬件触发不工作
- 触发源配置错误(如TIM定时器触发需配置TRGO输出);
- 触发极性/边沿配置错误(如上升沿/下降沿触发)。
六、ADC原理
1.常见的ADC类型
| 类型 | 转换速度 | 精度范围 | 功耗 | 成本 | 核心优势 |
|---|---|---|---|---|---|
| 逐次逼近型(SAR) | 中速 | 8~16 位 | 低 | 中 | 性价比高,适用场景广 |
| 流水线型(Pipeline) | 高速~超高速 | 8~20 位 | 中高 | 高 | 高速 + 高精度,适合射频 / 雷达 |
| 积分型(双斜率) | 极慢 | 16~24 位 | 低 | 低 | 抗干扰强,适合高精度测量 |
| 闪存型(Flash)并行比较型 | 超高速(最快) | 4~8 位 | 极高 | 极高 | 纳秒级转换,适合超高频信号 |
| Sigma-Delta(Σ-Δ) | 低速~中速 | 16~24 位 + | 低 | 中 | 超低噪声,适合音频 / 传感 |
2.并行比较型的ADC原理

精度低,成本高
3.逐次逼近型的ADC原理

转换速度慢
分辨率和采样速度相互矛盾,分辨率越高,采样速率越低
4.ADC的特性参数
分辨率 :ADC能辨别的最小模拟量 8 10 12 16 位等
转换时间:完成一次AD转换需要的时间,转换时间越短,采样率就越高
精度:最小刻度基础上叠加各种误差的参数,受ADC性能/温度/等影响
量化误差:用数字量近似表示模拟量,采用四舍五入原则,此过程产生的误差叫量化误差
5.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) | 36MHz(max) | 36MHz(max) |
| 采样时间 | 采样时间越长,转换结果相对越准确,但是转换速度就越慢 | |||
| 转换时间 | 与 ADC 时钟频率、分辨率和采样时间等有关 | |||
| 供电电压 | 2.4V~3.6V(全速运行) | |||
| 参考电压 | 一般为 3.3V | |||
| 输入电压 | 0-3.3V | |||
精度和时间成反比。
更多推荐



所有评论(0)