2025-05-16 2:56 PM
I'm setting up the ADC in "manual continuous" mode where hadc1.Init.ContinuousConvMode = DISABLE and then I call HAL_ADC_Start_IT() inside of HAL_ADC_ConvCpltCallback(). I get the first call to HAL_ADC_ConvCpltCallback and calling HAL_ADC_Start_IT() returns HAL_OK but the callback never gets called again.
What am I missing?
Thanks,
Chris
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
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.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
Solved! Go to Solution.
2025-05-17 1:54 AM - edited 2025-05-17 1:54 AM
Hello @cbcooper
It's better to handle the ADC conversion restart in the main loop, as shown in the example below:
// Global variable to indicate ADC conversion completion
volatile uint8_t adcConversionComplete = 0;
// ADC handle declaration
ADC_HandleTypeDef hadc1;
// Callback function for ADC conversion complete
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
// Set the flag to indicate conversion is complete
adcConversionComplete = 1;
}
int main(void) {
// HAL initialization
HAL_Init();
// ADC configuration (assuming hadc1 is properly configured elsewhere)
// ...
// Start ADC conversion in interrupt mode
HAL_ADC_Start_IT(&hadc1);
// Main loop
while (1) {
// Check if ADC conversion is complete
if (adcConversionComplete) {
// Reset the flag
adcConversionComplete = 0;
// Process the ADC data
uint32_t adcValue = HAL_ADC_GetValue(&hadc1);
// Use adcValue as needed
// Restart ADC conversion in interrupt mode
HAL_ADC_Start_IT(&hadc1);
}
// Other tasks can be performed here
}
}
2025-05-17 1:54 AM - edited 2025-05-17 1:54 AM
Hello @cbcooper
It's better to handle the ADC conversion restart in the main loop, as shown in the example below:
// Global variable to indicate ADC conversion completion
volatile uint8_t adcConversionComplete = 0;
// ADC handle declaration
ADC_HandleTypeDef hadc1;
// Callback function for ADC conversion complete
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
// Set the flag to indicate conversion is complete
adcConversionComplete = 1;
}
int main(void) {
// HAL initialization
HAL_Init();
// ADC configuration (assuming hadc1 is properly configured elsewhere)
// ...
// Start ADC conversion in interrupt mode
HAL_ADC_Start_IT(&hadc1);
// Main loop
while (1) {
// Check if ADC conversion is complete
if (adcConversionComplete) {
// Reset the flag
adcConversionComplete = 0;
// Process the ADC data
uint32_t adcValue = HAL_ADC_GetValue(&hadc1);
// Use adcValue as needed
// Restart ADC conversion in interrupt mode
HAL_ADC_Start_IT(&hadc1);
}
// Other tasks can be performed here
}
}
2025-05-19 11:07 AM
That works but why? I would much rather not have the ISR wait for the main code to get around to looking at the value before it starts acquiring the next.
2025-05-19 12:48 PM
You don't want to keep calling HAL_ADC_Start_IT directly from the callback as this would cause a lot of overhead and your other interrupts with lower priority will not be able to interrupt. And also your main while loop will not be able to run reliably as well.
So, do as @Saket_Om mentions or use a timer interrupt to start the ADC conversion.