高效实现单次非扫描多通道ADC数据采集的硬件与软件技术(STM32CubeMX开发)

高效实现单次非扫描多通道ADC数据采集的硬件与软件技术(STM32CubeMX开发)

一、需求背景与应用场景

单次非扫描多通道ADC采集指在一次触发信号下,依次采集多个指定通道的模拟信号(每个通道仅采集1次),适用于:

传统扫描模式(Scan Mode)虽能自动完成多通道序列转换,但存在固定通道顺序、无法动态跳过无效通道的局限。非扫描模式通过软件控制通道切换,结合DMA/中断实现高效采集,灵活性更高。

二、硬件技术:STM32 ADC核心特性与配置

1. STM32 ADC工作模式

核心优势:通过软件依次设置通道,实现“按需采集”,避免扫描模式的无用通道转换。

2. 硬件关键配置

(1)ADC时钟与采样时间

(2)参考电压

(3)通道与引脚分配

(4)DMA与中断

三、软件技术:STM32CubeMX配置与代码实现

1. STM32CubeMX配置步骤(以STM32F407为例)

(1)时钟树配置

(2)ADC参数配置

(3)DMA配置

(4)中断配置

(5)生成工程

选择MDK-ARM或STM32CubeIDE,生成HAL库工程。

2. 核心代码实现

(1)ADC与DMA初始化(自动生成,略作修改)

// adc.c(STM32CubeMX生成后修改)
#include "adc.h"

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
uint16_t adc_values[3]; // 存储3通道数据(IN0~IN2)

void MX_ADC1_Init(void) {
  ADC_ChannelConfTypeDef sConfig = {0};
  
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 10.5MHz
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE; // 非扫描模式
  hadc1.Init.ContinuousConvMode = DISABLE; // 单次转换
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1; // 非扫描模式,仅1个通道
  hadc1.Init.DMAContinuousRequests = DISABLE; // DMA单次传输
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 单次转换完成中断
  HAL_ADC_Init(&hadc1);
  
  // 配置通道0(IN0)
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  
  // 配置DMA
  hdma_adc1.Instance = DMA2_Stream0;
  hdma_adc1.Init.Channel = DMA_CHANNEL_0;
  hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  hdma_adc1.Init.Mode = DMA_NORMAL; // 单次传输
  hdma_adc1.Init.Priority = DMA_PRIORITY_MEDIUM;
  HAL_DMA_Init(&hdma_adc1);
  __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
}

(2)多通道采集函数(软件控制通道切换)

// 采集3个通道(IN0~IN2)
void ADC_MultiChannel_SingleShot(uint16_t *data) {
  // 通道0
  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&data[0], 1); // DMA传输1个数据
  while (HAL_ADC_GetState(&hadc1) != HAL_ADC_STATE_READY); // 等待转换完成
  
  // 通道1
  sConfig.Channel = ADC_CHANNEL_1;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&data[1], 1);
  while (HAL_ADC_GetState(&hadc1) != HAL_ADC_STATE_READY);
  
  // 通道2
  sConfig.Channel = ADC_CHANNEL_2;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&data[2], 1);
  while (HAL_ADC_GetState(&hadc1) != HAL_ADC_STATE_READY);
}

(3)主程序调用

// main.c
int main(void) {
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  
  uint16_t adc_data[3];
  
  while (1) {
    // 单次非扫描多通道采集
    ADC_MultiChannel_SingleShot(adc_data);
    
    // 数据处理(如转换为电压:V = adc_data * 3.3 / 4095)
    float v0 = adc_data[0] * 3.3f / 4095;
    float v1 = adc_data[1] * 3.3f / 4095;
    float v2 = adc_data[2] * 3.3f / 4095;
    
    HAL_Delay(1000); // 1秒采集1次
  }
}

参考代码 高效实现单次非扫描多通道ADC数据采集的硬件与软件技术+STM32cubemx开发 www.youwenfan.com/contentcns/180210.html

四、高效实现技巧

1. 减少通道切换开销

2. 优化采样时间

3. 低功耗设计

4. 数据校验

五、测试与验证

1. 测试工具

2. 性能指标

指标 非扫描模式(软件控制) 扫描模式(自动序列)
通道切换时间 2~5μs(软件配置) 0.5~1μs(硬件自动)
灵活性 高(动态选通道) 低(固定序列)
CPU占用率 中(需软件干预) 低(DMA自动)

六、总结

单次非扫描多通道ADC采集通过软件控制通道切换实现灵活采样,结合STM32CubeMX的直观配置,可高效完成多传感器数据采集。核心在于:

  1. 硬件配置:合理设置ADC时钟、采样时间、DMA单次传输;
  2. 软件优化:预配置通道参数、使用中断/DMA减少CPU干预;
  3. 场景适配:根据信号特性(阻抗、速度)调整采样策略,平衡精度与效率。

专注于matlab/simulink,电子电路,编程