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, // 第三次扫描
...
}
浙公网安备 33010602011771号