2021-08-13 08:02 AM
Hi,
I've configured the triple ADCs in Interleaved mode with DMA writing the ADC data in circular mode 2 on my Stm32f429 Discovery board.
What I'm trying to implement is:
So I wanted to know what is the best way to suspend the ADCs when the external interrupt happens with the HAL functions.
I'm already using this piece of code but I wanted to see if there's a more efficient way:
HAL_ADCEx_MultiModeStop_DMA(&hadc1);
HAL_ADC_Stop(&hadc2);
HAL_ADC_Stop(&hadc3);
Also, I need to know which address in the buffer was being written at the time the interrupt happened.
The AN4031 notes that:
The DMA_SxNDTR register contains the number of remaining data items at the moment when the stream was stopped so that the software can determine how many data items have been transferred before the stream was interrupted.
So I suppose that by using the code below I can find which address of the buffer was being written at the time suspension occurred?
Buffer_Addr_At_Trigger = (Total_Buffer_Length) - (DMA2_Stream0->NDTR);
Thanks in advance.
2021-08-25 05:28 PM
The NDTR solution that I suggested seems to work.
But I have some trouble for stopping the ADCs,
I first used this code to disable the DMA2 Stream0:
DMA2_Stream0->CR &= ~(1U<<0);
it resets the EN bit of the CR register, So I think it should stop the DMA.
And used this code to re-enable the DMA2 Stream0:
DMA2_Stream0->NDTR = buff_len; //buff_len being the total buffer length
DMA2_Stream0->CR |= (1U<<0);
It sets the NDTR value to the total buffer length, and then sets the EN bit of the CR register.
but it cannot re-enable my stream.
So then I used the code I suggested in the question, so in order to disable the DMA2 Stream0:
HAL_ADCEx_MultiModeStop_DMA(&hadc1);
HAL_ADC_Stop(&hadc2);
HAL_ADC_Stop(&hadc3);
and in order to re-enable it:
HAL_ADC_Start(&hadc3);
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)ADC_Buffer, buff_len);
but this one also seems to not restart my stream.
then I used the following lines to restart the stream and it seems to do the job:
MX_DMA_Init();
MX_ADC3_Init();
MX_ADC2_Init();
MX_ADC1_Init();
HAL_ADC_Start(&hadc3);
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)&ADC_Buffer, buff_len);
but then I realized that using this code the ADCs are acting weird and they seem to stop after a few milliseconds, although they are set in circular mode.
Also, another question came up in my mind and that is do I need to stop the ADCs? Or can I just stop the DMA without touching the ADCs?
If anyone has any better approach to suspend/restart the ADCs (or the DMA) I'd be grateful to hear them.