Configure the ADC to sample across 5 channels and enable DMA in circular mode.
Buffer Definition and Initialization
#define CHANNEL_COUNT 5
#define SAMPLES_PER_CHANNEL 100
static uint16_t raw_adc_buffer[CHAMPLES_PER_CHANNEL * CHANNEL_COUNT];
/**
* @brief Initialize ADC calibration and start DMA transfer
*/
void ADC_Startup(void)
{
HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)raw_adc_buffer,
SAMPLES_PER_CHANNEL * CHANNEL_COUNT);
}
Data Storage Pattern
When HAL_ADC_Start_DMA transfers data in u32 units to a u16 buffer, consecutive samples are paired:
| u32 Index | Upper 16-bit | Lower 16-bit |
|---|---|---|
| 0 | Channel 0 | Channel 1 |
| 1 | Channel 2 | Channel 3 |
| 2 | Channel 4 | Channel 0 |
| 3 | Channel 1 | Channel 2 |
| 4 | Channel 3 | Channel 4 |
For each channel, samples appear at indices 0, 5, 10, 15, etc. within the buffer. This arrangement allows straightforward access for averaging and filtering operations.
Data Processing
static volatile uint8_t data_ready_flag = 0;
static uint16_t channel_readings[CHANNEL_COUNT] = {0};
/**
* @brief Extract and filter ADC values for each channel
*/
static void Process_ADC_Data(void)
{
if (data_ready_flag == 1)
{
data_ready_flag = 0;
for (uint8_t ch = 0; ch < CHANNEL_COUNT; ch++)
{
uint32_t sum = 0;
uint16_t max_val = 0;
uint16_t min_val = 0xFFFF;
for (uint16_t idx = 0; idx < SAMPLES_PER_CHANNEL; idx++)
{
uint16_t sample = raw_adc_buffer[CHANNEL_COUNT * idx + ch];
sum += sample;
if (sample > max_val)
max_val = sample;
if (sample < min_val)
min_val = sample;
}
channel_readings[ch] = (sum - max_val - min_val) / (SAMPLES_PER_CHANNEL - 2);
}
}
}
/**
* @brief DMA transfer complete callback
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
data_ready_flag = 1;
}
The filtering algorithm removes maximum and minimum values before calculating the average, which effectively elimniates outliers from the dataset. Call Process_ADC_Data() in the main loop to retrieve filtered ADC values from channel_readings[0] through channel_readings[4].
Usage Example
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
ADC_Startup();
while (1)
{
Process_ADC_Data();
// Access filtered values
for (uint8_t i = 0; i < CHANNEL_COUNT; i++)
{
// Use channel_readings[i]
}
HAL_Delay(10);
}
}