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位右对齐为例)

  1. ADC校准 → 配置通道/采样时间 → 启动转换;
  2. 对指定通道的模拟电压采样,转换为数字值(0~4095);
  3. 转换结果存储到数据寄存器(ADC_DR);
  4. 触发中断/DMA,CPU读取结果(或DMA自动搬运);
  5. 数字值对应电压: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

精度和时间成反比。

Logo

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

更多推荐