概述
问题描述:
项目工程基于stm8s003芯片,以定时器2为例,定时器初始化后,发现第一次进入中断的时间不是设定的值,似乎是立即进入了中断。后面的中断时间就正常了。实际首次进入中断时间可以通过设置GPIO电平变化,用示波器测量得到。项目中由于在处理超声波测距时使用定时器来计数定时中断,初始化过程中偷偷的触发了中断导致第一次测距出现了误差。
问题分析:
- 软件规避:配置定时器时,先关闭更新中断,死等中断标志,清除标志后再开中断即可,跳过第一次的中断发生。
- 根本原因:当然是翻官方datasheet,查看timer2相关配置参数定位为配置定时器的分频值未生效。
手册章节18.4.1 Time base unit中关于Prescaler
The prescaler is based on a 16-bit counter controlled through a 4-bit register (in theTIMx_PSCR register). fCK_CNT = fCK_PSC/2(PSCR[3:0])
The prescaler value is loaded through a preload register. The shadow register, which contains the current value to be used is loaded as soon as the LS Byte has been written. The new prescaler value is taken into account in the following period (after the next counter update event).
翻译:预分频值是通过预分频寄存器加载而来,当TIMx_PSCR的低字节被写入时就会立即加载到预分频寄存器,从上图中可以看出只有在发生更新事件,预分频寄存器的值才会传递给影子寄存器(真正起作用但却看不到的寄存器)。
手册章节 18.6.15 TIMx_PSCR寄存器
PSCR contains the value which is loaded in the active prescaler register at each update event (including when the counter is cleared through the UG bit of the TIMx_EGR register). This means that a UEV must be generated so that a new prescaler value can be taken into account.
翻译:进一步说明需要触发更新事件后才能将新的预分频值加载到影子寄存器中从而使用新的预分频值来计算定时中断时间。产生更新事件取决于TIMx_EGR寄存器中UG位被置位。
- 解决方法:在新设定的预分频值未生效时,默认未分频时的定时器2运行频率为 16MHZ,设置的重装载值为1000,首次进入中断的理论时间:1000 * 0.0625ns = 62ns。在此次更新中断到来时先清除更新中断标志位,再允许中断更新就是正常设定的更新时间。
代码示例:
- 寄存器配置Timer2初始化
void Timer2_Init(void)
{
TIM2_IER &= ~MASK_TIM2_IER_UIE; //关闭更新中断
TIM2_ARRH = (uint8_t)(999 >> 8); //重装载值1000
TIM2_ARRL = (uint8_t)(999);
TIM2_PSCR = 4; //分频值(16分频)16MHZ / 16 = 1000KHZ,fCK_CNT =fCK_PSC / 2 ^(PSCR[3:0])
TIM2_CR1 |= MASK_TIM2_CR1_ARPE; //自动重装载值
TIM2_EGR |= MASK_TIM2_EGR_UG; //重新初始化计数器会引起更新中断
while ((TIM2_SR1 & 0x01) == 0); //第一次更新事件标志会立即进入,所以第一次计数不准,这里等待它
if (TIM2_SR1) TIM2_SR1 = 0x00; //清除第一次无效中断
TIM2_IER |= MASK_TIM2_IER_UIE; //允许更新中断
}
- 固件库配置Timer2初始化
void TImer2_Init(void)
{
TIM2_DeInit();
TIM2_TimeBaseInit( TIM2_PRESCALER_16, 999); //设置TIM2分频值16,重装载值1000
TIM2_PrescalerConfig( TIM2_PRESCALER_16, TIM2_PSCRELOADMODE_IMMEDIATE ); //配置加载分频值,触发UEV事件
TIM2_ClearITPendingBit(TIM2_IT_UPDATE); //清除更新中断标志位
TIM2_ITConfig( TIM2_IT_UPDATE, ENABLE ); //使能更新中断
TIM2_Cmd( ENABLE ); //使能TIM2
}
参考链接:
st社区论坛:https://community.st.com/s/question/0D50X00009XkWotSAF/premature-tim2-interrupt-happening-immediately-on-timer-start
最后
以上就是踏实大神为你收集整理的解决stm8s配置timer2中断时间不准的全部内容,希望文章能够帮你解决解决stm8s配置timer2中断时间不准所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复