2020-04-27 05:16 PM
I config ADC with DMA and TIM2. By TIM2 overflow starts ADC process for ADC1 ADC2 and ADC3 simultaneously. DMA collect ADC data and store to RAM. In debug i see that DMA for ADC1 transfer the same ADC data several times.
For example:
ADC1: 32, 32, 32, 32, 32, 32, 32 11, 11, 11, 11, 11
ADC2: 32, 11
ADC3: 32, 11
Problem not with ADC1. I arrange interrupt after end of conversion. It's interrupts by TIM2.
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hadc->Instance==ADC1)
{
memset(arrADC1, 0, ARR_LEN * sizeof(arrADC1[0]));
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_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_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
HAL_ADC_Start_DMA(hadc, (uint32_t *)arrADC1, ARR_LEN);
}
else if(hadc->Instance==ADC2)
{
memset(arrADC2, 0, ARR_LEN * sizeof(arrADC1[0]));
__HAL_RCC_ADC2_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
hdma_adc2.Instance = DMA2_Stream2;
hdma_adc2.Init.Channel = DMA_CHANNEL_1;
hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc2.Init.Mode = DMA_CIRCULAR;
hdma_adc2.Init.Priority = DMA_PRIORITY_HIGH;
hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc2);
}
else if(hadc->Instance==ADC3)
{
memset(arrADC3, 0, ARR_LEN * sizeof(arrADC1[0]));
__HAL_RCC_ADC3_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hdma_adc3.Instance = DMA2_Stream1;
hdma_adc3.Init.Channel = DMA_CHANNEL_2;
hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc3.Init.Mode = DMA_CIRCULAR;
hdma_adc3.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc3);
HAL_ADC_Start_DMA(hadc, (uint32_t *)arrADC3, ARR_LEN );
}
}
2020-04-27 06:11 PM
The code you linked does not initialize the ADC channels. This can be done with HAL_ADC_ConfigChannel calls in HAL.
It also doesn't call HAL_ADC_Init which I'm pretty sure is required.
2020-04-27 06:34 PM
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
//ADC1->CR1 |= ADC_CR1_EOCIE;
/* USER CODE END ADC1_Init 0 */
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
HAL_NVIC_SetPriority(ADC_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);
/* USER CODE END ADC1_Init 1 */
/** 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 = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_TRIPLEMODE_REGSIMULT;
multimode.DMAAccessMode = ADC_DMAACCESSMODE_1;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != 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_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
ADC1->CR1 |= ADC_CR1_EOCIE;
/* USER CODE END ADC1_Init 2 */
}
/**
* @brief ADC2 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC2_Init(void)
{
/* USER CODE BEGIN ADC2_Init 0 */
/* USER CODE END ADC2_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC2_Init 1 */
/* USER CODE END ADC2_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.ScanConvMode = ENABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.NbrOfConversion = 2;
hadc2.Init.DMAContinuousRequests = ENABLE;
hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc2) != 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_11;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC2_Init 2 */
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank =2;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END ADC2_Init 2 */
}
/**
* @brief ADC3 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC3_Init(void)
{
/* USER CODE BEGIN ADC3_Init 0 */
/* USER CODE END ADC3_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC3_Init 1 */
/* USER CODE END ADC3_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc3.Init.Resolution = ADC_RESOLUTION_12B;
hadc3.Init.ScanConvMode = ENABLE;
hadc3.Init.ContinuousConvMode = DISABLE;
hadc3.Init.DiscontinuousConvMode = DISABLE;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.NbrOfConversion = 2;
hadc3.Init.DMAContinuousRequests = ENABLE;
hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc3) != 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_1;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC3_Init 2 */
/* USER CODE END ADC3_Init 2 */
}
2020-04-27 06:35 PM
HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)
{
__IO uint32_t counter = 0U;
ADC_Common_TypeDef *tmpADC_Common;
/* Check the parameters */
assert_param(IS_ADC_CHANNEL(sConfig->Channel));
assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime));
/* Process locked */
__HAL_LOCK(hadc);
/* if ADC_Channel_10 ... ADC_Channel_18 is selected */
if (sConfig->Channel > ADC_CHANNEL_9)
{
/* Clear the old sample time */
hadc->Instance->SMPR1 &= ~ADC_SMPR1(ADC_SMPR1_SMP10, sConfig->Channel);
/* Set the new sample time */
hadc->Instance->SMPR1 |= ADC_SMPR1(sConfig->SamplingTime, sConfig->Channel);
}
else /* ADC_Channel include in ADC_Channel_[0..9] */
{
/* Clear the old sample time */
hadc->Instance->SMPR2 &= ~ADC_SMPR2(ADC_SMPR2_SMP0, sConfig->Channel);
/* Set the new sample time */
hadc->Instance->SMPR2 |= ADC_SMPR2(sConfig->SamplingTime, sConfig->Channel);
}
/* For Rank 1 to 6 */
if (sConfig->Rank < 7U)
{
/* Clear the old SQx bits for the selected rank */
hadc->Instance->SQR3 &= ~ADC_SQR3_RK(ADC_SQR3_SQ1, sConfig->Rank);
/* Set the SQx bits for the selected rank */
hadc->Instance->SQR3 |= ADC_SQR3_RK(sConfig->Channel, sConfig->Rank);
}
/* For Rank 7 to 12 */
else if (sConfig->Rank < 13U)
{
/* Clear the old SQx bits for the selected rank */
hadc->Instance->SQR2 &= ~ADC_SQR2_RK(ADC_SQR2_SQ7, sConfig->Rank);
/* Set the SQx bits for the selected rank */
hadc->Instance->SQR2 |= ADC_SQR2_RK(sConfig->Channel, sConfig->Rank);
}
/* For Rank 13 to 16 */
else
{
/* Clear the old SQx bits for the selected rank */
hadc->Instance->SQR1 &= ~ADC_SQR1_RK(ADC_SQR1_SQ13, sConfig->Rank);
/* Set the SQx bits for the selected rank */
hadc->Instance->SQR1 |= ADC_SQR1_RK(sConfig->Channel, sConfig->Rank);
}
/* Pointer to the common control register to which is belonging hadc */
/* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */
/* control register) */
tmpADC_Common = ADC_COMMON_REGISTER(hadc);
/* if ADC1 Channel_18 is selected for VBAT Channel ennable VBATE */
if ((hadc->Instance == ADC1) && (sConfig->Channel == ADC_CHANNEL_VBAT))
{
/* Disable the TEMPSENSOR channel in case of using board with multiplixed ADC_CHANNEL_VBAT & ADC_CHANNEL_TEMPSENSOR*/
if ((uint16_t)ADC_CHANNEL_TEMPSENSOR == (uint16_t)ADC_CHANNEL_VBAT)
{
tmpADC_Common->CCR &= ~ADC_CCR_TSVREFE;
}
/* Enable the VBAT channel*/
tmpADC_Common->CCR |= ADC_CCR_VBATE;
}
/* if ADC1 Channel_16 or Channel_18 is selected for Temperature sensor or
Channel_17 is selected for VREFINT enable TSVREFE */
if ((hadc->Instance == ADC1) && ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) || (sConfig->Channel == ADC_CHANNEL_VREFINT)))
{
/* Disable the VBAT channel in case of using board with multiplixed ADC_CHANNEL_VBAT & ADC_CHANNEL_TEMPSENSOR*/
if ((uint16_t)ADC_CHANNEL_TEMPSENSOR == (uint16_t)ADC_CHANNEL_VBAT)
{
tmpADC_Common->CCR &= ~ADC_CCR_VBATE;
}
/* Enable the Temperature sensor and VREFINT channel*/
tmpADC_Common->CCR |= ADC_CCR_TSVREFE;
if((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR))
{
/* Delay for temperature sensor stabilization time */
/* Compute number of CPU cycles to wait for */
counter = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000U));
while(counter != 0U)
{
counter--;
}
}
}
/* Process unlocked */
__HAL_UNLOCK(hadc);
/* Return function status */
return HAL_OK;
}
2020-04-27 06:36 PM
All code below
2020-04-28 07:59 AM
I use 3 DMA stream and 3 data buffer. In debug all stream DMA registers are similar. But data buffer for master ADC1 filled by repeated data.
2020-04-28 08:09 AM
On picture - in arrADC3 - data from two adc channels. It OK. But in arrADC1 - repeated data from only one channel!
2020-04-28 12:38 PM
Read out and post content of ADC and DMA registers.
JW
2020-04-28 04:42 PM