快捷搜索:  汽车  科技

定时器触发中断方法(一使能定时器中断就立即进入中断程序)

定时器触发中断方法(一使能定时器中断就立即进入中断程序)嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!2、误计算。当我们基于定时器捕获功能进行信号周期、占空比测量过程中,如果需要统计更新事件时,就有可能因为统计这个不该统计的更新事件而带来误差。也就是说,计数器还没开始启动就先进了一次更新中断。这种情况很多时候对我们应用可能并无妨碍,但有时也可能带来些问题或麻烦。比方:1、误动作。本来打算基于定时器运作延时特定时间后再在更新中断里完成的动作,这样一来就会出现计数器还未开始工作就进中断执行当前本不该执行的动作了。

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(1)

我们在基于ST的标准库或基于CubeMx建立工程,当用到定时器并启用其更新中断时,可能会遇到一使能定时器中断且计算器还未开始计数就立即进入更新中断服务程序的情况。

可能出现该现象的场合大概像下面样子,即先使能定时器更新中断,然后才去启动计数器。

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(2)

我们会发现,刚一使能更新中断还未启动计数器,结果就跑到更新中断服务程序里。

看看下面截图 右边TIMER控制寄存器CEN还未置1,SR寄存器里的UIF【更新事件标志】已经置1了。

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(3)

也就是说,计数器还没开始启动就先进了一次更新中断。

这种情况很多时候对我们应用可能并无妨碍,但有时也可能带来些问题或麻烦。比方:

1、误动作。本来打算基于定时器运作延时特定时间后再在更新中断里完成的动作,这样一来就会出现计数器还未开始工作就进中断执行当前本不该执行的动作了。

2、误计算。当我们基于定时器捕获功能进行信号周期、占空比测量过程中,如果需要统计更新事件时,就有可能因为统计这个不该统计的更新事件而带来误差。

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。

点击这里找小助理0元领取嵌入式物联网学习资料(头条)

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(4)

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(5)

该问题怎么产生的呢?

问题是由于我们的TIMER初始化函数里,在对ARR/PSC等时基参数做好初始赋值后,软件做了个手动产生更新事件的操作,目的就是让刚才设置的那些时基参数立即生效,并让定时器基于这些新设置的参数开始运行。

代码大致是下面的层次结构及内容:

MX_TIM_Inxit(); ==》

HAL_TIM_Base_Init(&htim)==》

TIM_Base_SetConfig()

void TIM_Base_SetConfig(TIM_TypeDef *TIMx TIM_Base_InitTypeDef *Structure)

{

…..

/* Set the auto-reload preload */

MODIFY_REG(tmpcr1 TIM_CR1_ARPE Structure->AutoReloadPreload);

TIMx->CR1 = tmpcr1;

/* Set the Autoreload value */

TIMx->ARR = (uint32_t)Structure->Period ;

/* Set the Prescaler value */

TIMx->PSC = Structure->Prescaler;

if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))

{

/* Set the Repetition Counter value */

TIMx->RCR = Structure->RepetitionCounter;

}

/* Generate an update event to reload the Prescaler

and the repetition counter (only for advanced timer) value immediately */

TIMx->EGR = TIM_EGR_UG;

}

其中, TIMx->EGR = TIM_EGR_UG;这行代码就是用来手动产生更新事件的。

我们知道,STM32定时器中有几个由预装寄存器和影子寄存器组成的寄存器组,他们分别是TIMx_PSC TIMx_ARR TIMx_CCR TIMx_RCR. 【注:基本定时器或通用定时器没有RCR寄存器】

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(6)

那么如何消除这个问题呢?操作很简单,TIMER初始化完成之后,使能定时器更新中断之前加一句清除更新中断请求位的代码即可。比方类似下面操作。

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(7)

或许有人问,我在TIMER初始化过程中自己组织代码时没有手动产生更新事件似乎也没啥问题?定时器跑得好好的?即没有类似下面打叉的语句。

定时器触发中断方法(一使能定时器中断就立即进入中断程序)(8)

的确,没有这句产生更新事件的代码定时器也能跑。

芯片复位后,ARR的预装功能默认关闭,此时改写ARR预装寄存器相当于同时也更新了其影子寄存器【即实际起作用的寄存器】,但PSC和RCR预装寄存器的内容只能借助溢出产生更新事件更新到其影子寄存器而起作用。

我们以向上计数模式为例,更新事件基于当前用户给定的ARR值计数一个周期后发生溢出而产生,随之新的PSC和RCR值才会生效。即二者的生效时间要延后一个周期。 【注:基本定时器或通用定时器没有RCR寄存器】

如果说有人自行组织代码,先将ARR的预装控制位使能打开,然后才给ARR赋值,同样不手动产生更新事件,那又会怎么样呢?抛砖引玉,可以自行结合手册琢磨和测试下。

ST的库函数的写法是合理的,当然,如果紧跟着做个更新事件标志的清零就更佳了,或许未来这个地方可以再改善下。

顺便提下,当你自己尝试在代码里适时而巧妙地使用手动定时器更新操作时,或许会发现这还是个不可多得的一个小技巧。

好,这个话题就聊到这里。其实,多年前也在这里分享过该话题,只是没有单列出来。这次单列出来再分享下,以资提醒。

转载自:茶话MCU

文章来源于一使能定时器中断就立即进入中断程序?

原文链接:https://mp.weixin.qq.com/s/dyZt5LBXhj2bLNQXoVvubA

猜您喜欢: