2014-11-26 10:05 AM
I have transferred code for ADC using an interrupt from STM32F405 to STM32F302 but it seems that the interrupt is probably fired again immediatelly after return. I see it by a permanent lit of a LED and on scope at LED signal, too.
If I add HAL_ADC_Start_IT(&hadc1); at the end of the interrupt handler, the interrupt is not fired next. How to clear an interrupt flag or so?// main.h
#include ''stm32f3xx_hal.h''
#include ''stm32f302x8.h''
#include <
stdbool.h
>
// Macro -------------------------------------------------------------
#define SETPIN(port,pin) (port->BSRRL = pin)
#define CLRPIN(port,pin) (port->BSRRH = pin)
#define TSTPIN(port,pin) (port->IDR & pin)
#define TGLPIN(port,pin) (port->ODR ^= pin)
// Pin definitions
#define LED_PIN GPIO_PIN_15
#define LED_PORT GPIOA
// Function prototypes
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
#include ''main.h''
ADC_HandleTypeDef hadc1;
extern volatile bool adc1done;
//------------------------------------------------------------------------------
int main(void)
{
HAL_Init();
SystemClock_Config();
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
SETPIN(LED_PORT,LED_PIN);
HAL_Delay(1000);
CLRPIN(LED_PORT,LED_PIN);
HAL_Delay(1000);
HAL_ADC_Start_IT(&hadc1);
while (1)
{
if (adc1done)
{
// process data
adc1done = false;
}
}
}
//------------------------------------------------------------------------------
// System Clock Configuration
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
__SYSCFG_CLK_ENABLE();
}
//------------------------------------------------------------------------------
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA15 for LED */
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
//------------------------------------------------------------------------------
/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
//Common config
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.Overrun = OVR_DATA_OVERWRITTEN;
HAL_ADC_Init(&hadc1);
//Configure Regular Channel
sConfig.Channel = ADC_CHANNEL_10; // OpAmp2 output
sConfig.Rank = 1;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.SamplingTime = ADC_SAMPLETIME_601CYCLES_5;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
#include ''main.h''
extern ADC_HandleTypeDef hadc1;
volatile uint32_t ticks;
volatile bool adc1done;
//------------------------------------------------------------------------------
void SysTick_Handler(void)
{
ticks++;
HAL_IncTick();
}
//------------------------------------------------------------------------------
void ADC1_IRQHandler(void)
{
uint16_t data;
SETPIN(LED_PORT,LED_PIN);
NVIC_ClearPendingIRQ(ADC1_IRQn);
if (__HAL_ADC_GET_FLAG(&hadc1, ADC_FLAG_EOC))
{
data = ADC1->DR;
// preprocess and store data
adc1done = true;
__HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_EOC);
}
CLRPIN(LED_PORT,LED_PIN);
}
// stm32f3xx_hal_msp.c
#include ''stm32f3xx_hal.h''
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADC1)
{
/* Peripheral clock enable */
__ADC1_CLK_ENABLE();
__HAL_RCC_ADC1_CONFIG(RCC_ADC1PLLCLK_DIV4);
/* Peripheral interrupt init*/
/* Sets the priority grouping field */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
HAL_NVIC_SetPriority(ADC1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(ADC1_IRQn);
}
}
2014-11-26 10:38 AM
If it keeps re-entering you're qualifying the wrong flag. Reading the DR should be sufficient to satiate an ADC EOC interrupt.
2014-11-30 02:06 PM
Yes, ADC->DR resets EOC flag.
I have found the first bug in stm32f3xx_hal_adc_ex.c, in function HAL_ADC_ConfigChannel: line 4280 must beif (sConfig->Channel >= ADC_CHANNEL_10) // i.e. also equal
without it my setting of a rather long sample time for Chan10 was written into wrong register so the shortest sample time was used.
The second bug must be in function
HAL_ADC_Start_IT(&hadc1)
because it does not work (interrupt is continuously fired) but
__HAL_ADC_ENABLE(&hadc1);
while (__HAL_ADC_GET_FLAG(&hadc1, ADC_FLAG_RDY) == RESET);
__HAL_ADC_ENABLE_IT(&hadc1, ADC_IT_EOC);
ADC1->CR |= ADC_CR_ADSTART;
works.
Unfortunatelly, such errorneous STMCube library rather than useful is infuriating (I am not sure about suitable English expression :-))
2015-01-15 12:41 AM
Hi,
Regarding the two bugs you mention:Regards,
Heisenberg. ________________ Attachments : Example_ADC_ContinuousOrTIM_ITorDMA_STM32F302R8-Nucleo.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1MA&d=%2Fa%2F0X0000000blo%2FkoiOFXY.F8OOgqKLm5.c8XQwvmss1sVjYAdIOCG2EOs&asPdf=false2015-01-16 04:08 AM
Hello, Heisenberg,
Thank you for a response and the example. I will study it. Ragarding the channel 10 sampling time, you see, that I corrected the code myself. Regarding ADC, I normally use DMA but I need to switch an external AMUX between the ADC conversions in this application.