Simultaneous regular mode with two ADCs (F303)
Posted: Sun Jan 19, 2025 8:23 pm
Hi, my HAL skills have got pretty rusty, so out of curiosity I asked AI to help with a simple code which will print out two ADC
channels conversions triggered simultaneously by TIM8 with a 100mS period.
After a couple of discussions with AI
it suggested to me following code, which looks complete on the first glance, and it builds and flashes into my F303 fine.
The issue is it hangs on calling the ADC routine readADCValues(); (when I comment it out it prints out zero results).
If you perhaps may spot an obvious issue there I would appreciate..
channels conversions triggered simultaneously by TIM8 with a 100mS period.
After a couple of discussions with AI

The issue is it hangs on calling the ADC routine readADCValues(); (when I comment it out it prints out zero results).
If you perhaps may spot an obvious issue there I would appreciate..
Code: Select all
#include <Arduino.h>
#include <stm32f3xx_hal.h>
// Define ADC pins
#define ADC1_CHANNEL_PIN PA0 // Example: ADC1_IN1 (PA0)
#define ADC2_CHANNEL_PIN PA1 // Example: ADC2_IN2 (PA1)
// Timer configuration
#define TRIGGER_TIMER TIM8 // Use Timer 8 for triggering
// Global variables to store ADC values
volatile uint16_t adc1_value = 0;
volatile uint16_t adc2_value = 0;
// Handles for ADCs and Timer
ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;
TIM_HandleTypeDef htim8;
void setupADC() {
// Enable clocks for ADCs, GPIO, and Timer
__HAL_RCC_ADC12_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_TIM8_CLK_ENABLE();
// Configure GPIO pins for ADC (PA0 for ADC1, PA1 for ADC2)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// ADC1 initialization
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
HAL_ADC_Init(&hadc1);
// Configure ADC1 channel (PA0)
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_61CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
// ADC2 initialization
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
HAL_ADC_Init(&hadc2);
// Configure ADC2 channel (PA1)
sConfig.Channel = ADC_CHANNEL_2;
HAL_ADC_ConfigChannel(&hadc2, &sConfig);
// Enable dual ADC mode for simultaneous sampling
ADC_MultiModeTypeDef multimode = {0};
multimode.Mode = ADC_DUALMODE_REGSIMULT;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);
// Enable ADCs
HAL_ADC_Start(&hadc1);
HAL_ADC_Start(&hadc2);
}
void setupTimer() {
// Configure TIM8 for trigger generation
htim8.Instance = TIM8;
htim8.Init.Prescaler = (SystemCoreClock / 10000) - 1; // Set timer clock to 10 kHz
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 1000 - 1; // Trigger every 100 ms (10 Hz)
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim8);
// Configure TIM8 to generate TRGO (trigger output)
TIM_MasterConfigTypeDef masterConfig = {0};
masterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; // Trigger on timer update event
masterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &masterConfig);
// Start the timer
HAL_TIM_Base_Start(&htim8);
}
void readADCValues() {
// Wait for conversion to complete
while (!__HAL_ADC_GET_FLAG(&hadc1, ADC_FLAG_EOC)) {}
while (!__HAL_ADC_GET_FLAG(&hadc2, ADC_FLAG_EOC)) {}
// Read ADC values
adc1_value = HAL_ADC_GetValue(&hadc1);
adc2_value = HAL_ADC_GetValue(&hadc2);
}
void setup() {
Serial.begin(9600);
setupADC();
setupTimer();
Serial.println("Setup complete. Starting ADC sampling...");
}
void loop() {
// Read ADC values (updated after each timer-triggered conversion)
readADCValues();
// Print ADC values
Serial.print("ADC1 Value: ");
Serial.print(adc1_value);
Serial.print("\tADC2 Value: ");
Serial.println(adc2_value);
//delay(100);
}