2023-08-03 02:08 AM - edited 2023-08-03 02:45 AM
Hi.
I am using STM32G070RB.
I need to sequentially receive values from 5 channels using ADC DMA.
If normal circumstances, the ADC data of PA0 should be stored in Array[0] and the ADC data of PA1 should be stored in Array[1].
However, currently experiencing a bug where PB0's ADC data is stored in Array[0], and PA0's ADC data is stored in Array[1].
PB0's ADC data is a variable value, and the ADC data of other pins is a fixed value.
PB0's ADC data should come out with continuously changing values in the array[4].
Can you give me some advice where i made a mistake?
main.c
void ADC_DMA_TC_Callback()
{
asm("nop");
}
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART3_UART_Init();
MX_TIM15_Init();
MX_TIM16_Init();
/* USER CODE BEGIN 2 */
LL_ADC_StartCalibration(ADC1);
while(LL_ADC_IsCalibrationOnGoing(ADC1));
LL_DMAMUX_SetRequestID(DMAMUX1, LL_DMAMUX_CHANNEL_0, LL_DMAMUX_REQ_ADC1);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA));
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)ADCVal);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, 5);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
LL_ADC_Enable(ADC1);
while (LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0);
//LL_TIM_EnableCounter(TIM15);
LL_ADC_REG_StartConversion(ADC1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
stm32g0xx_it.c
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
if(LL_DMA_IsActiveFlag_TC1(DMA1))
{
LL_DMA_ClearFlag_TC1(DMA1);
ADC_DMA_TC_Callback();
}
/* USER CODE END DMA1_Channel1_IRQn 0 */
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
/* USER CODE END DMA1_Channel1_IRQn 1 */
}
Solved! Go to Solution.
2023-08-04 04:39 AM
Most likely a problem because of ADC overrun. If it happens, it messes up the channel order. It can happen, for example, because of bus contention, but, while debugging, it basically happens all the time. You have to process it in the ADC interrupt by restarting the ADC channel sequence and DMA at the beginning.
2023-08-04 04:39 AM
Most likely a problem because of ADC overrun. If it happens, it messes up the channel order. It can happen, for example, because of bus contention, but, while debugging, it basically happens all the time. You have to process it in the ADC interrupt by restarting the ADC channel sequence and DMA at the beginning.
2023-08-04 05:06 AM
Thank you for answer.
2023-08-04 06:02 AM
Hello @Todg ,
Thank you for your question.
Q : Can you give me some advice where I made a mistake?
A : The mistake probably come from a bad initialization sequence. I downloaded your code and, indeed, I observed the one byte shift in the ADCVal array. (IN0 in Array[1], IN2 in Array[2], ...).
Copy this 2 lines :
LL_ADC_StartCalibration(ADC1); while(LL_ADC_IsCalibrationOnGoing(ADC1));
And insert it between the labels (before the init):
/* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */
Best Regards,
Pierre
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2023-08-04 03:54 PM
Thank you!