2015-12-02 07:00 AM
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?
2016-02-15 05:05 PM
I circumvented this in my application by checking the Lock in the ADC handle like this:
if (AdcHandle->Lock == HAL_UNLOCKED) conversion_complete = TRUE;2016-02-15 08:14 PM
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.