解决STM32 Timer定时器开机立即进入中断问题(HAL库)[转载]

【转载】STM32 Timer定时器开机立即进入中断问题(HAL库)

  • 问题1
  • 问题2
  • F407定时器更新中断问题(TIM_IT_Update中断)
  • STM32 定时器有时一开启就进中断的话题
  • [STM32CubeF4] HAL中的定时器中断处理函数,存在重复进入的隐患

  • 问题1

    原文链接:https://blog.csdn.net/Robotzzg/article/details/90712340

    学习过程中发现配置号Timer定时器功能之后,原本应该定时到指定的时间再进入中断,结果MCU开机就会进入一次中断,不符合逻辑,所以尝试解决这个问题。

    拜读各大佬的博客后发现没有HAL库的解决办法,于是转身向Google走去,找到了解决办法,分享给大家。
    解决办法

    在TIM初始化函数 HAL_TIM_Base_Init() 与 HAL_TIM_Base_Start_IT();

    之间加一条语句 __HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF); //注意将htim7改成自己的timer

    其中TIM_SR_UIF是 Update interrupt Flag 寄存器。

    原因就是HAL库中定时器初始化后没有更新中断标志位,__HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF)后清除了更新中断标志位,此时TIM_SR_UIF为0,中断产生后TIM_SR_UIF为1。

    另外

    细心的朋友会发现TIM_SR_UIF其实是SR(定时器状态寄存器)的最低位,初始化时若TIM_SR_UIF为1则SR也为1,若TIM_SR_UIF为0则SR也为0,因此存在另一种解决办法:将__HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF);换成htim7.Instance->SR = 0也是可以的。

    示范

    /**
      * @brief TIM7 Initialization Function
      * @param None
      * @retval None
      */
    void MX_TIM7_Init(uint16_t arr, uint16_t psc)
    {
     
      /* USER CODE BEGIN TIM7_Init 0 */
     
      /* USER CODE END TIM7_Init 0 */
     
      TIM_MasterConfigTypeDef sMasterConfig = {0};
     
      /* USER CODE BEGIN TIM7_Init 1 */
    	//(uint32_t)ceil(SECOND_WAKEUP) * 10000 / 2, 8400 - 1
      /* USER CODE END TIM7_Init 1 */
      htim7.Instance = TIM7;
      htim7.Init.Prescaler = psc;
      htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim7.Init.Period = arr;
      htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
      if (HAL_TIM_Base_Init(&htim7) != HAL_OK)// 定时器初始化
      {
        Error_Handler();
      }
      /* USER CODE BEGIN TIM7_Init 2 */
     
       __HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF);//添加这条语句解决问题
       //htim7.Instance->SR = 0; //这是另一种解决办法
     
       HAL_TIM_Base_Start_IT(&htim7);//开启定时器中断
     
      /* USER CODE END TIM7_Init 2 */
    }
    

    问题2

    原文链接:https://blog.csdn.net/qq_40945384/article/details/106716108

    TIMx->EGR = TIM_PSCReloadMode;这段语句就是把EGR寄存器的UG位配置为1,UG位说明如下

    看到了对TIMX->EGR寄存器UG位的解释,就明白了,官方库中让PSC预分频器立即更新的方式竟然是粗暴的强行产生一次事件更新,程序在定时器配置之后会被强行进入一次中断。好了,到此整个问题的诊断结束,接下来探究一下解决办法。

    通过上网搜索,有一种较广泛的说法是在使能定时器之前调用TIM_ClearITPendingBit(TIM1, TIM_IT_Update);但是在我的工程中使用这种办法并没有效果。

    我坚信羊毛都是出在羊身上~~~~~

    果然在手册上查到了TIMX->CR1寄存器

    该寄存器的URS位如下解释:

    TIMX->CR1寄存器的URS位特别提到了设置EGR寄存器UG位产生的更新事件。URS位配置为1时则可以筛选掉除了计数上溢、下溢以外的更新事件。

    最后在定时器配置过程中,修改预分频器PSC之前的位置调用一下TIM4->CR1 |= TIM_CR1_URS;语句可完美解决定时器配置后默认进入一次中断的问题。

    F407定时器更新中断问题(TIM_IT_Update中断)

    https://www.armbbs.cn/forum.php?mod=viewthread&tid=4187&fromuid=58

    STM32 定时器有时一开启就进中断的话题

    http://www.51hei.com/bbs/dpj-40940-1.html

    [STM32CubeF4] HAL中的定时器中断处理函数,存在重复进入的隐患

    https://www.armbbs.cn/forum.php?mod=viewthread&tid=94677&extra=page%3D1

    HAL库启动定时器运行和中断是HAL_TIM_Base_Start_IT(); 但是,执行一次中断后就会停止。需要在中断函数中重新调用一次才可继续执行。然而,第二次打开的时候就直接进入中断了,定时器没有完整计数!
    分析结果如下:
    定时器的中断处理函数是:HAL_TIM_IRQHandler(&htim4);//以定时器4作为例子。
    这个函数里面的update中断处理部分如下://update的中断处理最常用,其他的冗长代码省略。
    /* 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); //这个句子很诡异!查询得知这个是禁止update event中断!并不是容易理解的“清除中断标志”
    #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
    htim->PeriodElapsedCallback(htim);
    #else
    HAL_TIM_PeriodElapsedCallback(htim);
    #endif /
    USE_HAL_TIM_REGISTER_CALLBACKS */
    }
    }

    全程的处理函数,没有清除中断标志!!需要人为在HAL_TIM_PeriodElapsedCallback()中加上__HAL_TIM_CLEAR_FLAG(htim,TIM_FLAG_UPDATE);

    总结: __HAL_TIM_CLEAR_FLAG()和__HAL_TIM_CLEAR_IT()是完全不同的意义,及其容易混淆!

    物联沃分享整理
    物联沃-IOTWORD物联网 » 解决STM32 Timer定时器开机立即进入中断问题(HAL库)[转载]

    1 评论

    1. 谢谢大神,完美的解决了我既要手动更新EGR,同时又不想进入那个手动更新产生的中断.再次感谢

    发表评论