Skip to main content
Visitor II
December 12, 2023
Question

Problem with the ADC measurement with DMA and RTC

  • December 12, 2023
  • 1 reply
  • 873 views

HI

I have a problem. I want to measure 4 channels of the ADC every 20 seconds (this is more time but for now it is like this for testing) through an RTC interrupt, then print by the serial terminal.
What happens is that it shows me the reading every 20 seconds but all the channels are always at 0.

Config ADC1 and DMA

 

void ADC1_DMA_Init(void)
{
	 __HAL_RCC_ADC1_CLK_ENABLE();
	 ADC_ChannelConfTypeDef sConfig = {0};
	 hadc1.Instance = ADC1;
	 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
	 hadc1.Init.ContinuousConvMode = DISABLE;
	 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
	 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
	 hadc1.Init.DiscontinuousConvMode = ENABLE;
	 hadc1.Init.NbrOfDiscConversion = ADC_BUFF_SIZE;
	 hadc1.Init.NbrOfConversion = ADC_BUFF_SIZE;
	 if (HAL_ADC_Init(&hadc1) != HAL_OK)
	 {
		 Error_Handler();
	 }
	 
	 HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);
	 HAL_NVIC_EnableIRQ(ADC1_IRQn);
	 
	 sConfig.Channel = ADC_CHANNEL_10;
	 sConfig.Rank = ADC_REGULAR_RANK_1;
	 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
	 {
		 Error_Handler();
	 }
	 sConfig.Channel = ADC_CHANNEL_11;
	 sConfig.Rank = ADC_REGULAR_RANK_2;
	 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
	 {
		 Error_Handler();
	 }
	 sConfig.Channel = ADC_CHANNEL_1;
	 sConfig.Rank = ADC_REGULAR_RANK_3;
	 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
	 {
		 Error_Handler();
	 }

	 sConfig.Channel = ADC_CHANNEL_4;
	 sConfig.Rank = ADC_REGULAR_RANK_4;
	 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
	 {
		 Error_Handler();
	 }
	 
	 __HAL_RCC_DMA1_CLK_ENABLE();
	 hdma_adc1.Instance = DMA1_Channel1;
	 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_HIGH;
	 if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
	 {
		 Error_Handler();
	 }
	 __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
	 __HAL_DMA_ENABLE_IT(&hdma_adc1, DMA_IT_TC);
	 HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
	 HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
	 ADC_Enable(&hadc1);
}

 

 

stm32f1xx_it.c

 

void DMA1_Channel1_IRQHandler(void)
{
 if (__HAL_DMA_GET_FLAG(&hdma_adc1, DMA_IT_TC) != 0x00u)
 {
	 __HAL_DMA_CLEAR_FLAG(&hdma_adc1, DMA_IT_TC);
 }
}
...
void ADC1_2_IRQHandler(void)
{
 if (__HAL_ADC_GET_FLAG(&hadc1, ADC_FLAG_EOC))
 {
	 __HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_EOC);
 }
}
...
void RTC_Alarm_IRQHandler(void)
{
 if (__HAL_RTC_ALARM_GET_FLAG(&hrtc, RTC_IT_ALRA) != (uint32_t)RESET)
	{
 	HAL_ADCEx_Calibration_Start(&hadc1);
 	HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&adcValue, ADC_BUFF_SIZE);
 	results.Cbat = adcValue[0];
 	results.Csol = adcValue[1];
 	results.Vbat = adcValue[2];
 	results.Vsol = adcValue[3];

 	myprintf("\nVbat: %-5d Vsol: %-5d Cbat: %-5d Csol: %-5d\n", results.Vbat, results.Vsol, results.Cbat, results.Csol);
 	HAL_ADC_Stop_DMA(&hadc1);

 	HAL_RTC_GetAlarm(&hrtc, &sAlarm, RTC_ALARM_A, FORMAT_BIN);
 	sAlarm.AlarmTime.Seconds = sAlarm.AlarmTime.Seconds + 0x20;
 	HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, FORMAT_BIN);
 	__HAL_RTC_ALARM_CLEAR_FLAG(&hrtc, RTC_IT_ALRA);
 	__HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
	 }
}

 

 

uint16_t adcValue[4];

In DMA1_Channel1_IRQHandler and ADC1_2_IRQHandler I have no code. In RTC_Alarm_IRQHandler is where I start the ADC conversion and save the data in the adcValue buffer, then pass it to a structure and display it on the serial terminal.
myprintf is a function to print by UART1.

I am programming a stm32f103rct6 microcontroller with platformio.

Result obtained by serial terminal every 20 seconds:
Vbat: 0 Vsol: 0 Cbat: 0 Csol: 0

 

    This topic has been closed for replies.

    1 reply

    Super User
    December 12, 2023

    Wait for DMA to complete before using its values. DMA happens in the background.