cancel
Showing results for 
Search instead for 
Did you mean: 

STM32f103 EXTI external interrupt problem.

KSido.1
Associate

For 3 days I have been increasing with the problem.

I explain what's going on.

I am trying to read using stm32f103 the width of the PWM pulses coming from the 4 channels of the RC receiver. I configured external EXTI interrupts, on 4 channels, edge triggered falling and rising.

It is also set to TIMER4 with its own overflow interrupt that counts the time.

When a channel interrupts from a rising edge, the time from TIM4 is taken and the variable containing the number of TIM4 reloads is reset, when a falling edge occurs, the width time is calculated based on the previous data.

Incoming PWM width is 500 for all channels, falling and rising edges occur at the same time for all 4 channels.

The problem is that sometimes (every few dozen interrupts), the value of Width_Time ... takes an unexpected value, as if it had been miscalculated. I suspect there is something wrong with variable sharing in TIMER - EXTI interrupts.

I will go for help, maybe one of the respected group members was aggravating with such a problem?

volatile uint16_t Width_Time_C1 = 0;
volatile uint16_t Width_Time_C2 = 0;
volatile uint16_t Width_Time_C3 = 0;
volatile uint16_t Width_Time_C4 = 0;
 
volatile uint16_t Start_Time_C1 = 0;
volatile uint16_t Start_Time_C2 = 0;
volatile uint16_t Start_Time_C3 = 0;
volatile uint16_t Start_Time_C4 = 0;
 
volatile uint8_t Prel_Time_C1 = 0;
volatile uint8_t Prel_Time_C2 = 0;
volatile uint8_t Prel_Time_C3 = 0;
volatile uint8_t Prel_Time_C4 = 0;
 
 
void TIM4_IRQHandler(void)
{
  HAL_TIM_IRQHandler(&htim4);
 
  if(Prel_Time_C1<10)   Prel_Time_C1++;
  if(Prel_Time_C2<10)   Prel_Time_C1++;
  if(Prel_Time_C3<10)   Prel_Time_C1++;
  if(Prel_Time_C4<10)   Prel_Time_C1++;
}
 
 
void EXTI9_5_IRQHandler(void)
{
	if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_8) != 0x00u)
	{
		if(((GPIOE -> IDR) & GPIO_IDR_IDR8) == GPIO_IDR_IDR8)  // C1
		{
		  Start_Time_C1  = TIM4->CNT;
		  Prel_Time_C1   = 0;
		}
		else
		{
		   Width_Time_C1 = ((Prel_Time_C1*1000) + TIM4->CNT) - Start_Time_C1;
 
		   if( (Width_Time_C1 > 520) || (Width_Time_C1 <490) )
		   {
		   }
		 }
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_8);
	}
}
 
 
void EXTI15_10_IRQHandler(void)
{
	if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_10) != 0x00u)
	{
 
		if(((GPIOE->IDR) & GPIO_IDR_IDR10) == GPIO_IDR_IDR10)// c2
		{
		  Start_Time_C2  = TIM4->CNT;
		  Prel_Time_C2   = 0;
		}
		else
		{
		  Width_Time_C2 = ((Prel_Time_C2*1000) + TIM4->CNT) - Start_Time_C2;
 
		  if( (Width_Time_C2 > 520) || (Width_Time_C2 <490) )
		  {
		  }
		}
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_10);
	}
 
 
 
	if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_12) != 0x00u)
	{
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_10);
 
		if(((GPIOE->IDR) & GPIO_IDR_IDR12) == GPIO_IDR_IDR12)//c3
		{
		  Start_Time_C3  = TIM4->CNT;
		  Prel_Time_C3   = 0;
		}
		else
		{
		  Width_Time_C3 = ((Prel_Time_C3*1000) + TIM4->CNT) - Start_Time_C3;
 
		  if( (Width_Time_C3 > 520) || (Width_Time_C3 <490) )
		  {
		  }
		}
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_12);
	}
 
 
	if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_15) != 0x00u)
	{
 
		if(((GPIOE->IDR) & GPIO_IDR_IDR15) == GPIO_IDR_IDR15) //c4
		{
		  Start_Time_C4  = TIM4->CNT;
		  Prel_Time_C4   = 0;
		}
		else
		{
		  Width_Time_C4 = ((Prel_Time_C4*1000) + TIM4->CNT) - Start_Time_C4;
 
		  if( (Width_Time_C4 > 520) || (Width_Time_C4 <490) )
		  {
		  }
		}
		__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_15);
	}
}
 
 
void MX_GPIO_Init(void)
{
 
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  /*Configure GPIO pins : PE8 PE10 PE12 PE15 */
  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
 
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
 
}
 
 
void MX_TIM4_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 71;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 999;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_Base_Start_IT(&htim4);
}

2 REPLIES 2
TDK
Guru

Using a timer in IC mode would be a more accurate way to measure pulse durations. Using EXTI is subject to interrupt delays/jitter. Only one interrupt can run at once. If more than one get triggered, the timer keeps ticking away until it gets handled.

If you feel a post has answered your question, please click "Accept as Solution".

Incrementing the same variable doesn't seem to be what you wanted to implement.

Half the other code clears the wrong interrupt sources. You want to do it earlier so it clears before it exits and doesn't tail-chain a second time.

>>For 3 days I have been increasing with the problem.

Perhaps sit with a colleague and do a code walk.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..