2025-09-29 12:55 AM - last edited on 2025-09-29 7:13 AM by Imen.D
Hello,
I have two channels on ADC1 and I want to trigger a s ample separately, every two seconds from first channel and every 10th second from second channel. I am using interrupts so after the adc trigger I get an interrupt when conversion is done. But it seems i only get a sample or read it from the first channel. I am new to stm32 microcontroller so i am not sure what can be wrong. I am configering everything and using an interrupt handler for reading the ready sample. I get the interrupt after each trigger but it seems i am getting the value from the first channel.
__HAL_RCC_VREF_CLK_ENABLE(); // enable the internal voltage reference
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.GainCompensation = 0;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc1.Init.OversamplingMode = DISABLE;
ADC_RegisterHandle(&hadc1);
sConfig.SamplingTime = ADC_SAMPLETIME_391CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = ADC_REGULAR_RANK_1;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = ADC_REGULAR_RANK_2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
__HAL_ADC_CLEAR_FLAG(&adc1, ADC_FLAG_EOC);
__HAL_ADC_CLEAR_FLAG(&adc1, ADC_FLAG_OVR);
__HAL_ADC_CLEAR_FLAG(&adc1, ADC_FLAG_EOS);
HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC1_IRQn);
__HAL_ADC_ENABLE_IT(&adc1, ADC_IT_EOC);
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
Public void ADC_RegisterHandle(ADC_HandleTypeDef *handle)
{
hadc1 = handle;
}
This is my interrupt handler:
Public void ADC1_IRQHandler(void)
{
if (__HAL_ADC_GET_FLAG(adc1, ADC_FLAG_EOS)){ //test code to check set flags
if (NULL != adcValueCB) {
// just for test to see if interrupt is received
}
}
if (__HAL_ADC_GET_FLAG(adc1, ADC_FLAG_EOC)){
if (NULL != adcValueCB) {
// just for test to see if interrupt is received
}
}
if (__HAL_ADC_GET_FLAG(adc1, ADC_FLAG_OVR)){
if (NULL != adcValueCB) {
// just for test to see if interrupt is received
}
}
HAL_ADC_IRQHandler(adc1); //hal library from stm32
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if (hadc->Instance == ADC1) {
uint32_t ch1 = HAL_ADC_GetValue(hadc); // here I always get the value from first sampled channel, channel 5
adcValueCB(&ch1); // return value to rest of the program
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR); // clear flags that are not cleared by getting the value
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOS);
}
}
In the code loop I trigger the conversion:
Get the number of channel I want a sample from, sent from the rest of the program at different intervals
sConfig.Channel = inputChannel;
sConfig.Rank = GetChannelRank(inputChannel);
HAL_ADC_ConfigChannel(&adc1, &sConfig);
SysCtlDelay(10); // delay of 10 ms after changing channels to stabilize
HAL_ADC_Start_IT(&hadc1);
Is there anything I am missing?
Best regards,
Gergana
Edit by ST Moderator to apply source code formatting. Please see the Posting Tips for how to properly post source code.
2025-10-01 8:00 AM
Hello @GTanova ,
Your issue stems from the way the ADC is configured and used to sample multiple channels separately at different intervals, but with only one conversion configured at a time.
ADC Channel Configuration Persistence:
HAL_ADC_ConfigChannel() configures the ADC channel in the regular sequence. But the ADC peripheral may not fully update the channel selection immediately or reliably between conversions, especially if the ADC is not fully stopped or if the configuration is not done properly.
Rank and Scan Mode:
Since you have ScanConvMode = DISABLE and NbrOfConversion = 1, the ADC expects only one channel configured. Configuring multiple channels with different ranks but scan disabled is inconsistent.
Changing Channel on the Fly:
Changing the channel configuration dynamically before each conversion is possible but requires careful handling:
Rank Usage:
If scan mode is disabled, ranks beyond 1 are ignored. Your second channel configuration with rank 2 is not used.
Based on your application (You want to sample channel 5 every 2 seconds and channel 6 every 10 seconds separately.) here is how to solve it:
Here is a Code Snippet proposal, the argument channel in the requested channel that you want to update the configuration
Best regards,
Aime