cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F413 ADC DMA AnalogWatchdog not working in SleepMode

Pain
Associate II

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.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

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".

View solution in original post

2 REPLIES 2
TDK
Guru

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
Associate II

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(); 
  }