cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_ADC_ConvCpltCallback called twice

paul2
Senior
Posted on December 02, 2015 at 16:00

Hi,

I have an issue with the ADC configuration below. ADC is triggered once (pulse = 5000, period 21000) by TIM3, but for some reason HAL_ADC_ConvCpltCallback is called twice.

TIM3

/*TIM3 init*/
void TIM3_Init(void) {
tim3.Instance = TIM3;
tim3.Init.Period = 21000; 
tim3.Init.Prescaler = 84; 
tim3.Init.ClockDivision = 0;
tim3.Init.CounterMode = TIM_COUNTERMODE_UP;
if (HAL_TIM_OC_Init(&tim3) != HAL_OK) {
}
sTimChannelConfig.OCMode = TIM_OCMODE_TOGGLE;
sTimChannelConfig.Pulse = 5000;
sTimChannelConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
/* Common configuration for all channels */
sTimChannelConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sTimChannelConfig.OCFastMode = TIM_OCFAST_DISABLE;
sTimChannelConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
sTimChannelConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_OC_ConfigChannel(&tim3, &sTimChannelConfig, TIM_CHANNEL_1) != HAL_OK) {
}
/* Output Compare Toggle Mode configuration: Channel2 */
sTimChannelConfig.OCMode = TIM_OCMODE_TIMING;
sTimChannelConfig.Pulse = 2500;
if (HAL_TIM_OC_ConfigChannel(&tim3, &sTimChannelConfig, TIM_CHANNEL_2) != HAL_OK) {
}
/* Output Compare Toggle Mode configuration: Channel3 */
sTimChannelConfig.OCMode = TIM_OCMODE_TIMING;
sTimChannelConfig.Pulse = 7500;
if (HAL_TIM_OC_ConfigChannel(&tim3, &sTimChannelConfig, TIM_CHANNEL_3) != HAL_OK) {
}
/* Start channel 2 in Active mode */
if (HAL_TIM_OC_Start_IT(&tim3, TIM_CHANNEL_1) != HAL_OK) {
}
/* Start channel 2 in Active mode */
if (HAL_TIM_OC_Start_IT(&tim3, TIM_CHANNEL_2) != HAL_OK) {
}
/* Start channel 3 in Active mode */
if (HAL_TIM_OC_Start_IT(&tim3, TIM_CHANNEL_3) != HAL_OK) {
/* Starting Error */
}
}

ADC1 (multi-mode with ADC2)

void ADC1_Init(void) {
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 0;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_CC1;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK) {
/* Initialization Error */
}
sConfig.Channel = ADC_CHANNEL_15;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/* Start the conversion process */
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*) &ADC1Converted, 2) != HAL_OK) {
}
/* enable interrupt */
if (HAL_ADC_Start_IT(&hadc1) != HAL_OK) {
}
/**Configure the ADC multi-mode*/
Multimode.Mode = ADC_DUALMODE_REGSIMULT;
Multimode.DMAAccessMode = ADC_DMAACCESSMODE_2;
Multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &Multimode);
}

DMA

if (hadc->Instance == ADC1) {
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO clock */
__GPIOC_CLK_ENABLE();
/* ADC1 Periph clock enable */
__ADC1_CLK_ENABLE();
/* Enable DMA2 clock */
__DMA2_CLK_ENABLE();
/*ADC1 GPIO Configuration*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*##-3- Configure the DMA streams ##########################################*/
/* Set the parameters to be configured */
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_VERY_HIGH;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_adc1);
/* Associate the initialized DMA handle to the the ADC handle */
__HAL_LINKDMA(hadc, DMA_Handle, hdma_adc1);
/*##-4- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt */
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

Callback

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc1) {
ADC2Buffered[ADC1BufferIndex] = ADC2Converted[0];
ADC2BufferIndex = ADC2BufferIndex + 1;
if (ADC2BufferIndex >= 200) {
ADC2BufferIndex = 0;
}
}

Now ADC1Buffered[] is filled with duplicated values because HAL_ADC_ConvCpltCallback is called twice per TIM3 trigger. Any thoughts?
2 REPLIES 2
bigbird
Associate
Posted on February 16, 2016 at 02:05

I circumvented this in my application by checking the Lock in the ADC handle like this:

   if (AdcHandle->Lock == HAL_UNLOCKED)

      conversion_complete = TRUE;

TDK
Guru
Posted on February 16, 2016 at 05:14

You're triggering the conversion twice here:

/* Start the conversion process */
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*) &ADC1Converted, 2) != HAL_OK) {
}
/* enable interrupt */
if (HAL_ADC_Start_IT(&hadc1) != HAL_OK) {
}

The second call does the same thing as the first, but uses interrupts (the ADC IRQ) instead of DMA.
If you feel a post has answered your question, please click "Accept as Solution".