9dome猫 发表于 2023-1-30 23:48

STM32F0 定时器中断 小白掉进的坑(FreeModbus)Timeout

1)STM32F0有多个定时器,对应多个IRQn

TIM1_BRK_UP_TRG_COM_IRQn    = 13,   /*!< TIM1 Break, Update, Trigger and Commutation Interrupt         */
TIM1_CC_IRQn                = 14,   /*!< TIM1 Capture Compare Interrupt                                  */
TIM3_IRQn                   = 16,   /*!< TIM3 global Interrupt                                           */
TIM6_IRQn                   = 17,   /*!< TIM6 global Interrupt                                           */
TIM14_IRQn                  = 19,   /*!< TIM14 global Interrupt                                          */
TIM15_IRQn                  = 20,   /*!< TIM15 global Interrupt                                          */
TIM16_IRQn                  = 21,   /*!< TIM16 global Interrupt                                          */
TIM17_IRQn                  = 22,   /*!< TIM17 global Interrupt                                          */

9dome猫 发表于 2023-1-30 23:55

2)通常每个IRQn对应一个zho中断函数

/**
* @briefThis function handles TIM14 global interrupt request.
* @paramNone
* @retval None
*/
void TIM14_IRQHandler(void)
{
HAL_TIM_IRQHandler(&Input_Handle);
}

9dome猫 发表于 2023-1-30 23:55

中断函数里通常会调用HAL_TIM_IRQHandler(&Input_Handle);这个函数来区分是哪一种中断
/**
* @briefThis function handles TIM interrupts requests.
* @paramhtim TIMhandle
* @retval None
*/
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
/* Capture compare 1 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET)
    {
      {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;

      /* Input capture event */
      if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
      {
          HAL_TIM_IC_CaptureCallback(htim);
      }
      /* Output compare event */
      else
      {
          HAL_TIM_OC_DelayElapsedCallback(htim);
          HAL_TIM_PWM_PulseFinishedCallback(htim);
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
      }
    }
}
/* Capture compare 2 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
      /* Input capture event */
      if((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
      {
      HAL_TIM_IC_CaptureCallback(htim);
      }
      /* Output compare event */
      else
      {
      HAL_TIM_OC_DelayElapsedCallback(htim);
      HAL_TIM_PWM_PulseFinishedCallback(htim);
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
}
/* Capture compare 3 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
      /* Input capture event */
      if((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
      {
      HAL_TIM_IC_CaptureCallback(htim);
      }
      /* Output compare event */
      else
      {
      HAL_TIM_OC_DelayElapsedCallback(htim);
      HAL_TIM_PWM_PulseFinishedCallback(htim);
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
}
/* Capture compare 4 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
      /* Input capture event */
      if((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
      {
      HAL_TIM_IC_CaptureCallback(htim);
      }
      /* Output compare event */
      else
      {
      HAL_TIM_OC_DelayElapsedCallback(htim);
      HAL_TIM_PWM_PulseFinishedCallback(htim);
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
}
/* TIM Update event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
      HAL_TIM_PeriodElapsedCallback(htim);
    }
}
/* TIM Break input event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
      HAL_TIMEx_BreakCallback(htim);
    }
}
/* TIM Trigger detection event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
      HAL_TIM_TriggerCallback(htim);
    }
}
/* TIM commutation event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET)
{
    if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) !=RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
      HAL_TIMEx_CommutationCallback(htim);
    }
}
}

9dome猫 发表于 2023-1-30 23:59

在这个函数里根据不同的中断,调用不同的回调函数,像最基本的计时中断,调用HAL_TIM_PeriodElapsedCallback(htim);

9dome猫 发表于 2023-1-30 23:59

问题来了:当我的程序需要用多个di开始定时器时,而且有相同的中断。开始我以为可以在HAL_TIM_IRQHandler(&Input_Handle);后面写自己的处理代码

void TIM14_IRQHandler(void)
{
HAL_TIM_IRQHandler(&Input_Handle);

//其他处理代码
}

9dome猫 发表于 2023-1-31 00:00

6)但是,在使用Freemodbus的时候FreeModbus用到的定时器在HAL_TIM_PeriodElapsedCallback(htim)中执行了TIMERExpiredISR();这个函数。

9dome猫 发表于 2023-1-31 00:02

7)当我用到另一个别的定时器的的时候,因为我在HAL_TIM_PeriodElapsedCallback(htim)这个函数里没有区分是哪个定时器产生的中断,所以当其他定时器产生中断时也顺便执行了属于FreeModbus的这个TIMERExpiredISR();处理函数。

9dome猫 发表于 2023-1-31 00:02

8)这样就导致了一个奇怪的xian现象:只有我一启动别的定时器。主机Modbus Poll的时候就会出现Timeout的情况。

在HAL_TIM_PeriodElapsedCallback(htim)中区分zh中断来源之后,问题就解决了。

9dome猫 发表于 2023-1-31 00:02

9)ken坑啊,都怪对库的执行sh顺序不了解。
页: [1]
查看完整版本: STM32F0 定时器中断 小白掉进的坑(FreeModbus)Timeout