cancel
Showing results for 
Search instead for 
Did you mean: 

ADC with timer and DMA not storing values om STM32L431

rickard2
Associate III

I am trying to use Tim6 with ADC and DMA2 to save 100 ADC values in a buffer. It seems to be working, DMA counter decreases and I get DMA interrupt, but only the first value in the array is stored, the rest are 0 (init values). Can someone help me understanding what is wrong?

void main()
	....
	for(i = 0; i < ADC_CONVERTED_DATA_BUFFER_SIZE; i++)
	{
		aADCxConvertedData[i] = 0;
	}
 
	Configure_ADC();
	Configure_DMA();
	Configure_TIM_TimeBase_ADC_trigger();
 
	__HAL_RCC_ADC_CLK_ENABLE();
	__HAL_RCC_DMA2_CLK_ENABLE();
	PrintDMA();
	HAL_TIM_Base_Start(&htim6);
	err = HAL_ADC_Start_DMA(&hadc1,(uint32_t *)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE);
	if (err != HAL_OK)
	{
		printf("DMA err %d\n\r", err);
	}
	PrintDMA();
 
	HAL_NVIC_SetPriority(DMA2_Channel3_IRQn, 0, 0);
	HAL_NVIC_EnableIRQ(DMA2_Channel3_IRQn);
 
	HW_TIM_Delay(100);	// wait 100 ms
 
	for(i = 0; i < 10; i++)
	{
		printf("%d\n\r", aADCxConvertedData[i]);
	}
}
	
	
void PrintDMA()
{
	printf("TIM6: %d: DMA2: %d: %d/%d\n\r", (int)htim6.Instance->CNT, (int)LL_DMA_IsActiveFlag_TC3(DMA2), LL_DMA_GetDataLength(DMA2, LL_DMA_CHANNEL_3), ADC_CONVERTED_DATA_BUFFER_SIZE);
	printf("En %d. Flags %d %d\n\r", LL_DMA_IsEnabledChannel(DMA2, LL_DMA_CHANNEL_3), (int)LL_DMA_IsActiveFlag_TE1(DMA2), (int)LL_DMA_IsActiveFlag_TE2(DMA2));
 
}
 
 
 
void Configure_ADC(void)
{
	//ADC_ChannelConfTypeDef sConfig = {0};
 
	/* USER CODE BEGIN ADC1_Init 1 */
 
	/* USER CODE END ADC1_Init 1 */
	/** Common config
	*/
	hadc1.Instance = ADC1;
	hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
	hadc1.Init.Resolution = ADC_RESOLUTION_12B;
	hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
	hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
	hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
	hadc1.Init.LowPowerAutoWait = DISABLE;
	hadc1.Init.ContinuousConvMode = DISABLE;
	hadc1.Init.NbrOfConversion = 1;
	hadc1.Init.DiscontinuousConvMode = DISABLE;
	hadc1.Init.NbrOfDiscConversion = 1;
	hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T6_TRGO;
	hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
	hadc1.Init.DMAContinuousRequests = DISABLE;
	hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
	hadc1.Init.OversamplingMode = DISABLE;
 
	hadc1.Init.ContinuousConvMode = ENABLE;
	hadc1.Init.DiscontinuousConvMode = DISABLE;
	hadc1.Init.DMAContinuousRequests = ENABLE;
 
	if (HAL_ADC_Init(&hadc1) != HAL_OK)
	{
	//Error_Handler();
	}
	
	if (HAL_ADC_ConfigChannel(&hadc1, ADC_CHANNEL_13) != HAL_OK)
	{
	//Error_Handler();
	}
}
 
void Configure_DMA(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
 
 
	HAL_DMA_DeInit(&hdma_adc1);
 
	__HAL_RCC_DMA2_FORCE_RESET();
	__HAL_RCC_DMA2_RELEASE_RESET();
 
	__HAL_RCC_ADC_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	/**ADC1 GPIO Configuration
	PC4     ------> ADC1_IN13
	*/
	GPIO_InitStruct.Pin = GPIO_PIN_4;
	GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
	/* ADC1 DMA Init */
	/* ADC1 Init */
	hdma_adc1.Instance = DMA2_Channel3;
	hdma_adc1.Init.Request = DMA_REQUEST_0;
	hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
	hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
	hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
	hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
	hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
	hdma_adc1.Init.Mode = DMA_NORMAL;
	hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
	if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
	{
		Error_Handler();
	}
 
	__HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1);
}
 
 
void Configure_TIM_TimeBase_ADC_trigger(void)
{
	
	TIM_MasterConfigTypeDef sMasterConfig = {0};
 
	/* USER CODE BEGIN TIM6_Init 1 */
 
	__HAL_RCC_TIM6_CLK_ENABLE();
	/* USER CODE END TIM6_Init 1 */
	htim6.Instance = TIM6;
	htim6.Init.Prescaler = 20;	//timer_prescaler-1;
	htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
	htim6.Init.Period = 1000;
	htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	htim6.Init.RepetitionCounter = 0;
	if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
	{
		Error_Handler();
	}
	sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
 
	sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
	if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
	{
		Error_Handler();
	}
 
}

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

Well, for one, you need to enable the ADC/DMA clocks before you start using them. __HAL_RCC_ADC_CLK_ENABLE(); should be before Configure_ADC, not after.

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

View solution in original post

3 REPLIES 3
TDK
Guru

Well, for one, you need to enable the ADC/DMA clocks before you start using them. __HAL_RCC_ADC_CLK_ENABLE(); should be before Configure_ADC, not after.

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

Thanks, it solved it!

However if I want to do a new DMA transfer i get error when running HAL_ADC_Start_DMA(&hadc1,(uint32_t *)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE); and it this line causes it  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL).

Even if I run

HAL_ADC_Stop_DMA(&hadc1);

HAL_DMA_Abort(&hdma_adc1);

HAL_ADC_Stop(&hadc1);

It is same result. Only way to do new transfer is to reset ADC. I would like to do a new transfer without reinit all modules

It works with HAL_ADC_Stop_DMA(&hadc1); but if I want to reinit ADC I must reset it. So no issue for now.