Skip to main content
PIvan.9
Associate III
January 4, 2022
Solved

How to use Analog Watchdog with DMA on NUCLEO-L476RG?

  • January 4, 2022
  • 2 replies
  • 1414 views

Hi folks,

I want to start ADC conversions on 2 regular channels of ADC1 block only after the voltage on one of the channels exceeds a certain limit, hence I'm using a watchdog feature.

After the watchdog will be triggered, I need to store 5 consequent values from each channel. Here is the relevant peace of code that I have so far:

void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc)
{
	HAL_ADC_Stop_IT(&hadc1);					// stop watchdog interrupts
 
	uint32_t adc_values[10] = {0};
	HAL_ADC_Start_DMA(&hadc1, adc_values, 10);	// read values from each channel after a watchdog has been triggered
	HAL_ADC_Stop_DMA(&hadc1);					// prevents continuous overwriting
 
	uint32_t A4_val = 0;
	uint32_t A5_val = 0;
 
	A4_val = adc_values[1];						// values from channel A4
	A5_val = adc_values[0];						// values from channel A5
	printf("A4 channel value is %lu\n", A4_val);
	printf("A5 channel value is %lu\n", A5_val);
 
	A4_val = adc_values[3];
	A5_val = adc_values[2];
	printf("A4 channel value is %lu\n", A4_val);
	printf("A5 channel value is %lu\n", A5_val);
 
	A4_val = adc_values[5];
	A5_val = adc_values[4];
	printf("A4 channel value is %lu\n", A4_val);
	printf("A5 channel value is %lu\n", A5_val);
 
	A4_val = adc_values[7];
	A5_val = adc_values[6];
	printf("A4 channel value is %lu\n", A4_val);
	printf("A5 channel value is %lu\n", A5_val);
 
	A4_val = adc_values[9];
	A5_val = adc_values[8];
	printf("A4 channel value is %lu\n", A4_val);
	printf("A5 channel value is %lu\n", A5_val);
	printf("--------------\n");
}

The problem is that this code works only up to a certain Sampling Time value and if I increase it to the maximum, then DMA starts to confuse values between channels or even outputs 0s.

It looks like I'm missing something, could anyone tell me how to combine watchdog with DMA properly?

This topic has been closed for replies.
Best answer by waclawek.jan

> HAL_ADC_Stop_DMA(&hadc1); // prevents continuous overwriting

You should wait until DMA stops itself (assuming you haven't set DMA to be circular).

It's not the best idea to printf() inside an interrupt.

JW

2 replies

waclawek.jan
waclawek.janBest answer
Super User
January 4, 2022

> HAL_ADC_Stop_DMA(&hadc1); // prevents continuous overwriting

You should wait until DMA stops itself (assuming you haven't set DMA to be circular).

It's not the best idea to printf() inside an interrupt.

JW

PIvan.9
PIvan.9Author
Associate III
January 4, 2022

Thanks a lot. I've moved all the printing to the main while loop and configured DMA using HAL_ADC_ConvCpltCallback. That helped, thanks

void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc)
{
 if (Watchdog_enable)
 {
 HAL_ADC_Stop_IT(&hadc1); // stop watchdog interrupts
 
 HAL_ADC_Start_DMA(&hadc1, adc_values, 10); // read values from each channel after a watchdog has been triggered
 
 DMA_enable = TRUE; // allow DMA start
 
 Watchdog_enable = FALSE; // disable subsequent watchdog interrupts
 }
}
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
 if (DMA_enable)
 {
 HAL_ADC_Stop_IT(&hadc1); // stop DMA interrupts
 
 HAL_ADC_Stop_DMA(&hadc1); // prevents continuous DMA overwriting
 
 Print_enable = TRUE; // allow printing the results
 }
}