【转载】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()是完全不同的意义,及其容易混淆!