【转载】STM32 Timer定时器开机立即进入中断问题(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()是完全不同的意义,及其容易混淆!

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值