2023-12-12 11:57 AM - edited 2023-12-12 12:27 PM
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();
}
}
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
2023-12-12 02:12 PM
Wait for DMA to complete before using its values. DMA happens in the background.