Skip to main content
Pain
Associate
September 17, 2021
Solved

STM32F413 ADC DMA AnalogWatchdog not working in SleepMode

  • September 17, 2021
  • 1 reply
  • 1347 views

The goal is to have the microcontroller which is in sleep mode, wake up when the voltage on a certain ADC channel drop below a set voltage.

The plan was to put the core to sleep via

 HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);

and have it wakeup via the analog watchdog interrupt. DMA is also enabled in circular mode.

The idea is that the ADC peripheral handles the task of monitoring the voltage without the need of the Cortex-M4 core running.

The issue I am running into is that the DMA interrupts after every conversion forcing the core to wakeup. I tried disabling the DMA interrupt and that causes the analog watchdog to not work.

Is it even possible to have the Analog watchdog functional with the core stopped or do I just have to wakeup every so often and check the ADC channel before going back to sleep.

Below is the ADC initialization code.

 uint16_t AnalogBuffer[1];
 ADC_ChannelConfTypeDef sConfig = {0}; 
 ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
 
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = ENABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; 
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.NbrOfConversion = 1;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_SEQ_CONV;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }
 
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
 AnalogWDGConfig.HighThreshold = 4095;
 AnalogWDGConfig.LowThreshold = lowerLimit;
 AnalogWDGConfig.Channel = ADC_CHANNEL_0;
 AnalogWDGConfig.ITMode = ENABLE;
 if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 if(HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AnalogBuffer, COUNTOF(AnalogBuffer)) != HAL_OK)
	{
		Error_Handler();
	}
 
 if (HAL_ADC_Start(&hadc1) != HAL_OK)
 {
 Error_Handler(); 
 }

Any and all help is appreciated. Thanks.

This topic has been closed for replies.
Best answer by TDK

If you just need a single channel, set it to monitor continuously (or off of a timer). You don't need to read the values with DMA for the watchdog to work.

Unsure how to do this with HAL exactly, but there's likely a way.

0693W00000DnaDzQAJ.png

1 reply

TDK
TDKBest answer
September 17, 2021

If you just need a single channel, set it to monitor continuously (or off of a timer). You don't need to read the values with DMA for the watchdog to work.

Unsure how to do this with HAL exactly, but there's likely a way.

0693W00000DnaDzQAJ.png

"If you feel a post has answered your question, please click ""Accept as Solution""."
Pain
PainAuthor
Associate
September 17, 2021

Thank You @TDK​ 

That worked :D

Below is the working HAL code. Thanks again!

 uint16_t AnalogBuffer[1];
 ADC_ChannelConfTypeDef sConfig = {0}; 
 ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
 
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = DISABLE;
 hadc1.Init.ContinuousConvMode = ENABLE;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; 
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.NbrOfConversion = 1;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }
 
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
 AnalogWDGConfig.HighThreshold = 4095;
 AnalogWDGConfig.LowThreshold = lowerLimit;
 AnalogWDGConfig.Channel = ADC_CHANNEL_0;
 AnalogWDGConfig.ITMode = ENABLE;
 if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 if (HAL_ADC_Start(&hadc1) != HAL_OK)
 {
 Error_Handler(); 
 }