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

探讨STM32定时器更新中断现象,即在某些情况下,仅使能更新中断就会触发一次中断。文章通过实验总结出正确的代码顺序,避免该现象发生,并提及UG位和URS位的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

本文转自:http://www.51hei.com/bbs/dpj-40940-1.html

    在用到STM32定时器的更新中断时,发现有些情形下只要开启定时器就立即进入一次中断。准确说,只要使能更新中断允许位就立即响应一次更新中断【当然前提是相关NVIC也已经配置好】。换言之,只要使能了相关定时器更新中断,不管你定时间隔多长甚至不在乎你是否启动了相关定时器,它都会立即进入一次定时器更新中断服务程序。

    以STM32F051芯片为例,做了几种不同顺序的组合测试。根据测试发现,的确有些情况下一运行**TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);** 【即使能更新中断】就立即进入更新中断服务程序。当然后面的中断都是正常的。

    老实说,这个问题比较容易忽视,有些情况下也无关紧要,但有些情况可能会给应用带来困扰。从ST MCU相关技术手册似乎并不能明显地找到关于这个问题的很合适或者逻辑性很强的前因后果。

经过验证测试,如果注意一下相关指令代码顺序是可以回避这个问题的。

手册截图

    先做更新中断标志的清除操作,即清除TIMx->SR寄存器里的UIF标志,然后做定时器更新中断的使能操作。至于开启相关定时器的指令摆放位置并不严格。下面是相关动作的操作顺序及结果,可以参考、验证之。这里共罗列了6种写法,其中有3种情形是会立即进入中断的,另外3种不会。
/*(1)。。。。。。不会立即进入更新中断程序。*/
TIM_ClearITPendingBit(TIM1, TIM_IT_Update); //清除更新中断请求位
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); //使能定时器1更新中断
TIM_Cmd(TIM1, ENABLE);                   //启动定时器

/*(2)。。。。。。不会立即进入更新中断程序。*/
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
TIM_Cmd(TIM1, ENABLE); 
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断

/*(3)。。。。。。不会立即进入更新中断程序。*/ 
TIM_Cmd(TIM1, ENABLE);
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断

/*(4)。。。。。。立即进入更新中断程序。*/
TIM_Cmd(TIM1, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位

/*(5)。。。。。。立即进入更新中断程序。*/
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
TIM_Cmd(TIM1, ENABLE);  

/*(6)。。。。。。立即进入更新中断程序。*/ 
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断
TIM_Cmd(TIM1, ENABLE); 
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位


 顺便提下关于定时器里UG位和URS位的使用,分别在TIMx->EGR和TIMx->CR1寄存器里。对UG位置1可以产生更新事件并对相关计数器和寄存器重新初始化,如果URS位为0的话,同时会产生更新中断。如果不希望对UG位置1的同时产生更新中断,得置URS位为1,否则会立即进入更新中断。 

这里写图片描述
这里写图片描述
这里写图片描述

本文转自:http://www.51hei.com/bbs/dpj-40940-1.html

### STM32定时器定时中断使用教程 #### 初始化TIM定时器STM32CubeIDE环境中,初始化TIM定时器涉及到多个方面。首先,在项目创建阶段通过图形化界面配置定时器的基础参数,如预分频系数(PSC)和自动重装载值(ARR),这些设置决定了定时周期[^1]。 对于具体实现而言,当利用库函数行编程时,`TIM_TimeBaseInit()`用于基础时间基底的设定;而针对特定功能需求比如捕获比较单元(CCx通道),则需调用相应接口完成步定制[^2]。 ```c // 配置定时器基本参数 void TIM_Config(void){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 999; // 自动重载值 TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 预分频数 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); } ``` #### 开启按键中断并使能定时器中断 为了确保按下按钮后能够及时响应启动计时过程,并允许后续处理逻辑依据超时事件作出反应,通常会结合外部IO端口产生的边沿信号来激活NVIC中的对应IRQ线程。旦检测到有效电平变化即刻触发ISR入口地址跳转执行关联服务例程内的代码片段——这里主要是打开TIMx->DIER寄存器里的UIE位从而开启更新事件请求机制。 ```c // 按键中断回调函数内启用定时器中断 void EXTI0_IRQHandler(void){ if (EXTI_GetITStatus(EXTI_Line0)!= RESET){ /* 清除标志 */ EXTI_ClearITPendingBit(EXTI_Line0); /* 启用定时器中断 */ TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); /* 用户自定义操作...*/ } } ``` #### 处理实际运行过程中可能出现的问题及其对策分析 有时即使正确设置了上述各项属性仍无法获得预期效果,例如PWM波形丢失等问题可能源于不当的选择了冲突资源或是错误理解硬件手册说明造成误配情形发生。此时建议仔细核对官方文档资料确认无遗漏之处之外还可以尝试调整相关参数直至恢复正常工作状态为止[^3]。 ```c // 调整定时器中断频率以解决问题 void Adjust_Timer_Frequency(void){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_DeInit(TIM2); TIM_TimeBaseStructure.TIM_Period = 999; // 修改后的自动重载值 TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 修改后的预分频数 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值