cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G070 ADC continuous conversion with 6 channel with DMA circular buffer does not work

JCuna.1
Senior

I have a code for stm32g070 which configure the adc as continuous conversion mode, sequencer set to fully configurable, scan conversion mode, dma continuous request, end of sequence conversion, oversampling mode right shift to 5 and ratio 32x.

Also I configure the dma as circular mode with peripheral to memory direction, using an array buffer uint16_t with 1200 halfword size, and enabling half transfer, complete transfer, and error transfer interrupt.

When the conversion start, the half transfer rise, but the buffer is completely full, and after complete transfer end, the buffer is overwritten.

Here the code:

void my_adc_start_scanning_channels_with_dma(void){
	__IO uint32_t backup_setting_adc_dma_transfer = 0U;
	__IO uint32_t wait_loop_index = 0UL;
 
	if(LL_ADC_IsInternalRegulatorEnabled(MY_ADC_HANDLER) != 0){
		if(LL_ADC_IsEnabled(MY_ADC_HANDLER)){
			LL_ADC_Disable(MY_ADC_HANDLER);
 
			while(LL_ADC_IsDisableOngoing(MY_ADC_HANDLER) != 0);
		}
 
		LL_ADC_DisableInternalRegulator(MY_ADC_HANDLER);
	}
 
	if(LL_DMA_IsEnabledChannel(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL) != 0){
		LL_DMA_DisableChannel(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
	}
 
//	LL_DMAMUX_SetRequestID(MY_ADC_DMA_HANDLER, LL_DMAMUX_CHANNEL_0, LL_DMAMUX_REQ_ADC1);
 
	LL_DMA_SetMode(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, LL_DMA_MODE_CIRCULAR);
 
	LL_DMA_SetDataTransferDirection(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
	LL_DMA_SetPeriphAddress(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, LL_ADC_DMA_GetRegAddr(MY_ADC_HANDLER, LL_ADC_DMA_REG_REGULAR_DATA));
	LL_DMA_SetMemoryAddress(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, (uint32_t)my_adc_buffer);
	LL_DMA_SetDataLength(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL, 1200);
 
	/* Enable DMA transfer interruption: transfer complete */
	LL_DMA_EnableIT_TC(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
 
	/* Enable DMA transfer interruption: half transfer */
	LL_DMA_EnableIT_HT(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
 
	/* Enable DMA transfer interruption: transfer error */
	LL_DMA_EnableIT_TE(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
 
	flag_my_adc_transfer_complete = 0;
	LL_DMA_EnableChannel(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
 
 
	// enabling voltage regulator for adc
	LL_ADC_EnableInternalRegulator(MY_ADC_HANDLER);
 
	/* Delay for ADC stabilization time */
	/* Wait loop initialization and execution */
	/* Note: Variable divided by 2 to compensate partially              */
	/*       CPU processing cycles, scaling in us split to not          */
	/*       exceed 32 bits register capacity and handle low frequency. */
	wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
	while (wait_loop_index != 0UL){
	  wait_loop_index--;
	};
 
	/* Disable ADC DMA transfer request during calibration */
	/* Note: Specificity of this STM32 series: Calibration factor is          */
	/*       available in data register and also transferred by DMA.          */
	/*       To not insert ADC calibration factor among ADC conversion data   */
	/*       in DMA destination address, DMA transfer must be disabled during */
	/*       calibration.                                                     */
	backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(MY_ADC_HANDLER);
	LL_ADC_REG_SetDMATransfer(MY_ADC_HANDLER, LL_ADC_REG_DMA_TRANSFER_NONE);
 
	// Run ADC self calibration
	LL_ADC_StartCalibration(MY_ADC_HANDLER);
 
	while(LL_ADC_IsCalibrationOnGoing(MY_ADC_HANDLER) != 0);
 
	/* Restore ADC DMA transfer request after calibration */
	LL_ADC_REG_SetDMATransfer(MY_ADC_HANDLER, backup_setting_adc_dma_transfer);
 
    /* Delay between ADC end of calibration and ADC enable.                   */
    /* Note: Variable divided by 2 to compensate partially                    */
    /*       CPU processing cycles (depends on compilation optimization).     */
    wait_loop_index = (ADC_DELAY_CALIB_ENABLE_CPU_CYCLES >> 1);
    while(wait_loop_index != 0){
      wait_loop_index--;
    }
 
    /* Enable ADC */
	LL_ADC_Enable(MY_ADC_HANDLER);
 
	while (LL_ADC_IsActiveFlag_ADRDY(MY_ADC_HANDLER) == 0);
 
	LL_ADC_REG_StartConversion(MY_ADC_HANDLER);
}12

15 REPLIES 15
JCuna.1
Senior

This is a capture before to configure DMA with buffer.

0693W00000GZ7PlQAL.pngAnd this is before to enabling ADC v regulator.

0693W00000GZ7Q0QAL.png 

This is before to calibrate and config ADC

0693W00000GZ7Q5QAL.png 

and this is right before to start adc conversion:

0693W00000GZ7QAQA1.png0693W00000GZ7QFQA1.png 

TDK
Guru

> However I am still having the issue with buffer filled completely when half transfer dma flag arise.

Looks like you're using stream 3. But HTIF3 isn't set in any of your screenshots, nor is execution within an interrupt.

If you feel a post has answered your question, please click "Accept as Solution".
JCuna.1
Senior

In these lines I configure dma channel 3 transfer interrupts

/* Enable DMA transfer interruption: transfer complete */
LL_DMA_EnableIT_TC(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
 
/* Enable DMA transfer interruption: half transfer */
LL_DMA_EnableIT_HT(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);
 
/* Enable DMA transfer interruption: transfer error */
LL_DMA_EnableIT_TE(MY_ADC_DMA_HANDLER, MY_ADC_DMA_CHANNEL);

And checking the DMA register it is effectively activated:

0693W00000GZ7XVQA1.png

HTIF3 is not set because the capture is just related to the register before to start a conversion.

JCuna.1
Senior

When the first half transfer interrupt arise I can see that a transfer complete interrupt flag also arise.

0693W00000GZ7YJQA1.png

The sampling time with dma is corroborated here, however, debugging process show me a complete buffer filled when Half transfer interrupt arise. The only thing I can do is inject a frequency known triangle signal in one of my adc channel and corroborate if the sample are following a correct behavior of a triangle signal.

When you stop the mcu in debugger, ADC and DMA keep running.

JW