cancel
Showing results for 
Search instead for 
Did you mean: 

ADC - DMA transfer fills only half buffer Stm32f7

CCont.1
Associate II

I'm using an adc channel of Stm32f767zi to get 1024 samples of an analog signal and transfer data directly in memory trough DMA. I configured ADC and DMA with cubeMx, and I start the conversions trough software, when it starts until the half DMA call back all seems work fine, but when the end call back is called the buffer still half empty and data are overwritten on the first half of buffer, there's a way to fill the entire buffer, or how to use double buffer? (this is my first experiment)

ADC Config:

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_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();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
}

DMA Config:

void MX_DMA_Init(void) 
{
 
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
 
}

Interrupts, main is empty, I'm working only trough iterrupts:

volatile uint32_t adc_buff[ADC_BUFF_DIM];               //BUFFER DEFINITION
 
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */
 
	if((GPIOC -> IDR & BUTTON_PIN) || (GPIOB -> IDR & ANLG_IN_CTRL_PIN))		//RISING EDGE
	{
		HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buff, ADC_BUFF_DIM);
 
		GPIOB -> ODR |= GREEN_LED_PIN;
	}
	else																		//FALLING EDGE
	{
		HAL_ADC_Stop_DMA(&hadc1);
		
		GPIOB -> ODR &= ~GREEN_LED_PIN;
	}
 
  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */
 
  /* USER CODE END EXTI15_10_IRQn 1 */
}
 
void DMA2_Stream0_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
 
  /* USER CODE END DMA2_Stream0_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_adc1);
  /* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
 
  /* USER CODE END DMA2_Stream0_IRQn 1 */
}

The two call back are empty, I'm checking this behaviour trough the debug mode

4 REPLIES 4

What happens if you remove this:

> HAL_ADC_Stop_DMA(&hadc1);

?

JW

TDK
Guru

> volatile uint32_t adc_buff[ADC_BUFF_DIM];

Without looking too much into it, it seems like you may be transferring ADC_BUFF_DIM values each of size uint16_t, not uint32_t.

Probably easiest solution is redefining your buffer as a uint16_t array.

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

I've tried if I remove the command simply it doesn't stop the adc run when I relase the button

Right, I already tought it was the problem, but if I gave a uint32_t * the routine doesn't increment the memory address on the next uint32_t free buffer address in memory?

Btw I've tried using uint16_t buffer and the results seem more reasonable because data became rappresentable on 12bit (27/26 bit with uint32_t) but in this case the buffer is already filled with the first half call back.

More over I noticed that the half call back is called twice the first time a conversion sarts: 1° conversion -> half call back -> half call back -> full call back -> half call back -> full call back -> ...