ADC多通道采集,开启DMA
硬件配置思路
使用DMA进行多通道ADC采集的主要优势:
-
无需CPU干预,自动传输数据
-
高效的数据流处理
-
可实现连续转换模式
// adc_dma.h #ifndef __ADC_DMA_H #define __ADC_DMA_H #include "main.h" #define ADC_CHANNEL_COUNT 3 // 通道数量 #define ADC_BUFFER_SIZE 100 // 每个通道的采样点数 extern ADC_HandleTypeDef hadc1; extern DMA_HandleTypeDef hdma_adc1; extern uint16_t adc_buffer[ADC_CHANNEL_COUNT * ADC_BUFFER_SIZE]; void ADC_DMA_Init(void); void ADC_Start_DMA_Conversion(void); uint16_t ADC_Get_Channel_Value(uint8_t channel, uint16_t sample_index); #endif // adc_dma.c #include "adc_dma.h" // ADC DMA缓冲区定义 // 数据排列: [CH0_S0, CH1_S0, CH2_S0, CH0_S1, CH1_S1, CH2_S1, ...] __ALIGN_BEGIN uint16_t adc_buffer[ADC_CHANNEL_COUNT * ADC_BUFFER_SIZE] __ALIGN_END; void ADC_DMA_Init(void) { // 初始化ADC if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } // 配置ADC通道 ADC_ChannelConfTypeDef sConfig = {0}; // 通道0配置 sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES; HAL_ADC_ConfigChannel(&hadc1, &sConfig); // 通道1配置 sConfig.Channel = ADC_CHANNEL_1; sConfig.Rank = 2; HAL_ADC_ConfigChannel(&hadc1, &sConfig); // 通道2配置 sConfig.Channel = ADC_CHANNEL_2; sConfig.Rank = 3; HAL_ADC_ConfigChannel(&hadc1, &sConfig); } void ADC_Start_DMA_Conversion(void) { // 启动ADC DMA转换 if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_CHANNEL_COUNT * ADC_BUFFER_SIZE) != HAL_OK) { Error_Handler(); } } // 获取指定通道的采样值 uint16_t ADC_Get_Channel_Value(uint8_t channel, uint16_t sample_index) { if (channel >= ADC_CHANNEL_COUNT || sample_index >= ADC_BUFFER_SIZE) { return 0; } // 计算数据在缓冲区中的位置 uint32_t index = sample_index * ADC_CHANNEL_COUNT + channel; return adc_buffer[index]; } // 获取指定通道的平均值(用于滤波) uint16_t ADC_Get_Channel_Average(uint8_t channel) { if (channel >= ADC_CHANNEL_COUNT) { return 0; } uint32_t sum = 0; for (uint16_t i = 0; i < ADC_BUFFER_SIZE; i++) { sum += ADC_Get_Channel_Value(channel, i); } return (uint16_t)(sum / ADC_BUFFER_SIZE); } // DMA传输完成回调函数(可选) void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { // 这里可以处理转换完成事件 // 例如:设置标志位、数据处理等 if (hadc->Instance == ADC1) { // ADC1转换完成处理 // 可以在这里进行数据后处理或通知其他任务 } }
数据缓冲区结构说明
缓冲区数据排列方式:
adc_buffer[] = { CH0_sample0, CH1_sample0, CH2_sample0, // 第一次扫描 CH0_sample1, CH1_sample1, CH2_sample1, // 第二次扫描 CH0_sample2, CH1_sample2, CH2_sample2, // 第三次扫描 ... }