2021-09-17 09:40 AM
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.
Solved! Go to Solution.
2021-09-17 09:57 AM
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.
2021-09-17 09:57 AM
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.
2021-09-17 01:38 PM
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();
}