你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
STMCU小助手 发布时间:2021-1-21 14:11
STM32 定时器有时一开启就进中断的话题
在用到STM32定时器的更新中断时,发现有些情形下只要开启定时器就立即进入一次中断。准确说,只要使能更新中断允许位就立即响应一次更新中断【当然前提是相关NVIC也已经配置好】。换言之,只要使能了相关定时器更新中断,不管你定时间隔多长甚至不在乎你是否启动了相关定时器,它都会立即进入一次定时器更新中断服务程序。
3 T/ {/ b' _8 |( R7 m3 S
以STM32F051芯片为例,做了几种不同顺序的组合测试。根据测试发现,的确有些情况下一运行TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); 【即使能更新中断】就立即进入更新中断服务程序。当然后面的中断都是正常的。
- [8 N8 Z2 k! s6 f. j/ e
老实说,这个问题比较容易忽视,有些情况下也无关紧要,但有些情况可能会给应用带来困扰。从STMCU相关技术手册似乎并不能明显地找到关于这个问题的很合适或者逻辑性很强的前因后果。

0 k: G& u( |/ O( J; \+ O* Y
经过验证测试,如果注意一下相关指令代码顺序是可以回避这个问题的。
5.1.jpg
" g( U6 @& S; M  T1 w7 e( j* w
先做更新中断标志的清除操作,即清除TIMx->SR寄存器里的UIF标志,然后做定时器更新中断的使能操作。至于开启相关定时器的指令摆放位置并不严格。下面是相关动作的操作顺序及结果,可以参考、验证之。这里共罗列了6种写法,其中有3种情形是会立即进入中断的,另外3种不会。
  1. IM_ClearITPendingBit(TIM1, TIM_IT_Update); //清除更新中断请求位7 r  t& M3 d3 R) R9 W
  2. TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); //使能定时器1更新中断4 ]  W( U0 {+ K" G: e3 q
  3. TIM_Cmd(TIM1, ENABLE); //启动定时器
复制代码
% P! H3 u  N% h1 J( Y

  f( O/ j7 R. |0 _% q
(1)不会立即进入更新中断程序。
  1. TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
    4 ?4 z1 D$ m/ e5 J7 L& k, i" P
  2. TIM_Cmd(TIM1, ENABLE);% M5 Q) O7 j1 t5 v
  3. TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断
复制代码

8 Z5 X) q4 }4 Z* j
(2)不会立即进入更新中断程序。
  1. TIM_Cmd(TIM1, ENABLE);8 j0 l4 J2 C& c) e7 j
  2. TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
    3 T# q6 _- h4 [* [0 A! b, c  b
  3. TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断
复制代码

2 [5 B) c1 W, e& R
(3)不会立即进入更新中断程序。
  1. TIM_Cmd(TIM1, ENABLE);
    * J+ ]8 x) w" K9 ^  B6 p$ G4 C
  2. TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断. V8 c- ?* K' n/ f" K
  3. TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
复制代码

* r9 Y+ l  _/ l! D! K3 Q0 o- Q
(4)立即进入更新中断程序。
  1. TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断
    1 Q( d9 I9 ]0 E( l
  2. TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位$ I- E5 b' W% g% Z
  3. TIM_Cmd(TIM1, ENABLE);
复制代码

  c4 U$ z. r! t# l3 e- ~
(5)立即进入更新中断程序。
  1. TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//使能定时器1更新中断
    : k& M, R7 B( Q- I5 R; {
  2. TIM_Cmd(TIM1, ENABLE);* t+ ~2 e& h: K9 N
  3. TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
复制代码
" P( J5 p2 L' @4 X7 L* H8 w5 b
(6)立即进入更新中断程序。

顺便提下关于定时器里UG位和URS位的使用,分别在TIMx->EGR和TIMx->CR1寄存器里。对UG位置1可以产生更新事件并对相关计数器和寄存器重新初始化,如果URS位为0的话,同时会产生更新中断。如果不希望对UG位置1的同时产生更新中断,得置URS位为1,否则会立即进入更新中断。
5.2.jpg
5.3.jpg
5.4.jpg
5.5.jpg
文章出处: 茶话MCU
. j4 n- M6 Y, t. _  F  U) p6 K4 y
赞 收藏 评论1 发布时间:2021-1-21 14:11

举报

1个回答
必胜鸟 回答时间:2021-5-26 14:29:58
  • TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除更新中断请求位
    8 _, i+ r. q: l% O1 V
, B  \' X" @% b0 U  B5 p: b. ^
: _: L! g' v, `) k6 V4 s
大神您好,我遇到您说的问题,两天没解决。+ Z! `5 d5 d! x
+ Z0 K* X. f; ?# _- O3 ?

; P6 ~- t- @4 x$ U0 [4 T. M- |上面这个库函数的操作结果是把定时器1的SR寄存器的第0位清0对吗?" R8 `; l6 c# _# b! w
' R- Z2 ^2 `5 c. w
" B0 \# {0 {4 B* A
      。。。。。7 b3 h, N5 I9 A% I+ J$ D$ w
      TIM1_SR1=0x00;            //清除状态寄存器;
% G: i/ \" h2 Q6 \6 q) j7 a      TIM1_CR1=0x01;            //使能计数器
$ I+ b7 e. }6 ~      TIM1_IER=0x01;            //更新中断使能
  x( {+ O' u+ `, U/ d. e
' O* p; o, Q$ a; U前面是设置计时初值,按这个操作仍然是直接进中断而不经定时的。相当于你的操作组合的第一种。: j0 ?: }0 W6 C% T1 c

3 w& O' m/ a+ ~! r6 e+ b1 L如果您看到回复,麻烦指点下在下,感激不尽
; C+ d# {- b* u* h7 n/ R  M7 b

, @9 r; ?+ p  ^; ?* d! y, q
" R$ Q: B! ~- x% a( l
+ F7 \$ c4 t  X8 o/ h
  y$ e$ b. q8 S1 y( ^6 u$ E

+ \& ?+ I* n) o+ B( f/ ^. W
$ a. X/ D2 i' [" l$ ]+ I- j
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版