STM32 ADC+DMA读取配置函数及实验

一、ADC+DMA读取配置函数

1. HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)

函数功能:

启动ADC的DMA传输,实现自动将ADC转换结果传输到指定内存地址。

参数说明:

复制代码
hadc:ADC句柄指针,指向ADC配置结构体
pData:目标内存地址指针,用于存储ADC转换结果
Length:DMA传输的数据长度(转换次数)

工作特点:
自动数据传输: ADC每次转换完成后,DMA自动将结果从ADC数据寄存器搬运到指定内存
连续/单次模式: 根据ADC配置支持连续转换或单次转换
多通道支持: 配合ADC扫描模式,可实现多通道自动转换和存储
**非阻塞操作:**启动后立即返回,转换在后台进行

配置要求:

ADC必须配置为DMA模式

DMA通道必须正确配置为外设到内存模式

在多通道扫描模式下,Length通常是通道数量的整数倍

2. HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

函数功能:

ADC转换完成回调函数,当DMA传输完成指定数量的转换结果时自动调用。

参数说明:

复制代码
hadc:触发回调的ADC句柄指针

工作特点:
自动调用: 由HAL库在DMA传输完成时自动调用
用户重写: 需要用户在代码中实现这个函数
安全处理: 在中断上下文中执行,适合处理转换结果
**多ADC支持:**通过hadc参数区分不同的ADC实例

二、示例实验

1. 实验现象

每隔500毫秒启动一次ADC的DMA转换,自动采集两个通道的模拟信号。当DMA传输完成两个通道的转换结果后,系统会自动调用回调函数,将原始ADC值转换为0.000V-3.300V的电压值,并通过串口以"输出1"和"输出2"的形式分别显示两个通道的电压测量值。串口上会看到每500毫秒输出一组两个电压值,实时反映两个ADC输入通道的电压变化情况。

2. 示例代码

ADC初始化

复制代码
/**
  * @brief  ADC1初始化函数
  */
void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};  // ADC通道配置结构体

  /** ADC通用配置 */
  hadc1.Instance = ADC1;                          // 设置ADC实例为ADC1
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;      // 启用扫描模式(多通道)
  hadc1.Init.ContinuousConvMode = DISABLE;        // 禁用连续转换模式(单次转换)
  hadc1.Init.DiscontinuousConvMode = DISABLE;     // 禁用间断模式
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 使用软件触发转换
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;     // 数据右对齐
  hadc1.Init.NbrOfConversion = 2;                 // 转换序列数为2(2个通道)
  
  // 初始化ADC,如果失败则调用错误处理函数
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** 配置规则通道1 */
  sConfig.Channel = ADC_CHANNEL_4;          // 设置ADC通道4
  sConfig.Rank = ADC_REGULAR_RANK_1;        // 设置通道在规则组中的排名为第1个
  sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;  // 设置采样时间为55.5个ADC时钟周期
  
  // 配置ADC通道4,如果失败则调用错误处理函数
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** 配置规则通道2 */
  sConfig.Channel = ADC_CHANNEL_5;          // 设置ADC通道5
  sConfig.Rank = ADC_REGULAR_RANK_2;        // 设置通道在规则组中的排名为第2个
  // 采样时间保持与通道4相同(55.5个ADC时钟周期)
  
  // 配置ADC通道5,如果失败则调用错误处理函数
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

DMA初始化

复制代码
/**
  * @brief  DMA初始化函数
  */
void MX_DMA_Init(void)
{
  // 使能DMA1时钟
  __HAL_RCC_DMA1_CLK_ENABLE();

  // DMA中断配置
  // 配置DMA1通道1中断(ADC1使用的DMA通道)
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);  // 设置中断优先级
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);          // 使能DMA中断
}

主函数

复制代码
uint16_t get[2] = {0};    // ADC原始值数组,用于存储两个通道的转换结果
float aaa[2] = {0.0f};    // 电压值数组,用于存储计算后的电压值

// 系统时钟配置函数声明
void SystemClock_Config(void);

/**
  * @brief  应用程序主函数
  * @retval int
  */
int main(void)
{
  // HAL库初始化
  HAL_Init();

  // 系统时钟配置
  SystemClock_Config();

  // 初始化所有配置的外设
  MX_GPIO_Init();           // GPIO初始化
  MX_DMA_Init();            // DMA初始化
  MX_ADC1_Init();           // ADC1初始化(配置为双通道扫描模式)
  MX_USART1_UART_Init();    // USART1串口初始化
  
  // 执行ADC校准
  HAL_ADCEx_Calibration_Start(&hadc1);

  // 主循环
  while (1)
  {
    // 启动ADC DMA传输,转换2个通道的数据到get数组
    HAL_ADC_Start_DMA(&hadc1, (uint32_t *)get, 2);
    
    // 延时500ms
    HAL_Delay(500);
  }
}

中断回调函数

复制代码
/**
  * @brief  ADC转换完成回调函数(DMA模式)
  * @param  hadc: ADC句柄指针
  */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  if(hadc->Instance == ADC1)
  {
    // 将ADC原始值转换为电压值(12位分辨率,参考电压3.3V)
    aaa[0] = (float)get[0] / 4095 * 3.3f;  // 通道4的电压值
    aaa[1] = (float)get[1] / 4095 * 3.3f;  // 通道5的电压值
    
    // 通过串口输出两个通道的电压值
    printf("\r\n输出1:%.3f\r\n输出2:%.3f\r\n", aaa[0], aaa[1]);
  }
}
相关推荐
bai5459361 天前
STM32 备份寄存器
stm32·单片机·嵌入式硬件
cold_Mirac1 天前
stm32-freertos和逻辑编程下堆栈功能的区分
stm32·单片机·嵌入式硬件
youcans_1 天前
【动手学STM32G4】(3)上位机实时显示多路波形
stm32·单片机·嵌入式硬件·上位机
铁手飞鹰1 天前
[HAL库分析—GPIO]
c语言·stm32·单片机·嵌入式硬件
徐某人..1 天前
网络编程学习--第一天
arm开发·单片机·学习·arm
yrx0203071 天前
STM32F103通过L298N驱动两相4线步进电机【42步进电机】
stm32·单片机·嵌入式硬件·步进电机
安当加密1 天前
基于 SLA 的操作系统双因素安全登录:USB Key 与 OTP 动态口令实践
单片机·嵌入式硬件·安全
硅农深芯1 天前
六大核心芯片:MCU/SOC/DSP/FPGA/NPU/GPU 的区别与应用解析
单片机·嵌入式硬件·fpga开发
就是蠢啊1 天前
51单片机——DS18B02(三)
单片机·嵌入式硬件·51单片机
Darken031 天前
基于TIM定时中断的----内外时钟源选择
stm32·单片机·tim定时器·时钟源