cancel
Showing results for 
Search instead for 
Did you mean: 

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

PIvan.9
Associate II

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?

1 ACCEPTED SOLUTION

Accepted Solutions

> 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

View solution in original post

2 REPLIES 2

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

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
    }
}