STM32 定时器开关导致延时不准确
我的代码设置如下:定时器配置为向上计数模式,计数间隔为1us,10us中断一次,来实现一个10us的延时。
开关定时器方法:
定时器中断函数()
{
关闭定时器,清除CEN位;----------------此时CNT寄存器有时是0,有时是1
执行处理代码;
打开定时器,设置CEN位;----------------CNT计数起点受制于前面,如果是1,那么下次9us后进入中断,而不是10
}
疑问:
进入中断后,立即关闭定时器时,CNT寄存器值可能每次不一样,导致开启定时器时计数起点不同。难道芯片每次进入中断后运行到关闭定时器的那行代码的时间会变化吗?大神能否解释一下?
想到的解决办法:
1、添加对CNT寄存器设置操作
定时器中断函数()
{
关闭定时器,清除CEN位;----------------此时CNT寄存器有时是0,有时是1
执行处理代码;
CNT = 0;
打开定时器,设置CEN位;----------------CNT计数起点受制于前面
}
2、将定时器设置为单脉冲模式----onePulse,查看参考手册发现设置为单脉冲模式,定时器溢出后自动停止计数器。
以上两种方法是否可行?哪种方法好呢,会不会引入其它问题。请大神指点!谢谢!
1、中断需要压栈、退栈等操作,并非楼主所想那个10us操作。楼主在这个非常紧张的中断里中断中又要关闭定时器,又要启动定时器,还能剩下多少指令执行时间?。
2、其实要做到个10uS的中断,无需关心CNT的值,只要细心配置好定时器中断参数,每次中断就是10uS,在中断里,执行小于10uS(这个10Us能做的事很有限,还要扣除堆栈操作))的操作就是。 本帖最后由 stm1024 于 2018-7-4 13:05 编辑
话说这个是不是放错板块了……
不太明白你为什么要采用这种方式,通常清除中断标志就可以了。以最简单的TIM6/7为例:void TIM6_IRQHandler(void)
{
if(TIM_GetITStatus(TIM6 ,TIM_IT_Update)!= RESET)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_13,ba);
ba=1-ba;
}
TIM_ClearITPendingBit(TIM6,TIM_FLAG_Update);
}其实你可以多看看别人是怎么实施的。
oceane 发表于 2018-7-4 17:00
非要从其中选择一个,本人选择2方案。不过建议最好还是换种实现方式
抱歉再打扰一下,您能否讲一下单脉冲模式具体的运作原理?
我的理解,计数器单脉冲模式:
1、计数器开启(cen=1)
2、计数器开始计数
3、计数器溢出中断,同时计数器自动关闭(cen=0,cnt=0),进入中断执行代码2
4、中断代码最后开启计数器(cen=1),接着会从步骤2重复运行
配置成单脉冲模式,以上运行逻辑正常吗?我看手册上会有脉冲产生,我没有配置那些,是否会产生什么脉冲波形?(我不要脉冲波形)
本帖最后由 oceane 于 2018-7-4 13:06 编辑
为什么要关闭定时器呢?关闭后再打开就不是精确的10us中断了,关闭打开也需要时间肯定会有延时不准。 wenyangzeng 发表于 2018-7-4 13:26
1、中断需要压栈、退栈等操作,并非楼主所想那个10us操作。楼主在这个非常紧张的中断里中断中又要关闭定时 ...
感谢回复,中断中执行代码大于10us,所以进入中断就把它关闭了。 stm1024 发表于 2018-7-4 13:02
话说这个是不是放错板块了……
不太明白你为什么要采用这种方式,通常清除中断标志就可以了。以最简单的TI ...
感谢回复是发错地方了我在中断中必须关闭定时器,因为代码执行时间要远大于10
oceane 发表于 2018-7-4 13:00
为什么要关闭定时器呢?关闭后再打开就不是精确的10us中断了,关闭打开也需要时间肯定会有延时不准。 ...
感谢回复,中断中执行代码大于10us,所以进入中断就把它关闭了。 既然代码执行时间大于10us为什么还要在10us的中断里面执行这段代码呢。
如果不是必须在中断中执行的东西可以放到中断外面去执行,另外就是优化一下代码,也许能在10us内执行完 子曰好人 发表于 2018-7-4 14:06
既然代码执行时间大于10us为什么还要在10us的中断里面执行这段代码呢。
如果不是必须在中断中执行的东西可 ...
感谢回复,这里的定时器的作用只是控制程序进行的作用 miraclexue 发表于 2018-7-4 13:41
感谢回复,中断中执行代码大于10us,所以进入中断就把它关闭了。
既然中断中执行代码大于10us,楼主设置这个10us中断有何意义? wenyangzeng 发表于 2018-7-4 15:26
既然中断中执行代码大于10us,楼主设置这个10us中断有何意义?
此定时器主要目的是控制程序反复执行,您暂可不必注意这点,您看我提出的两个解决方案哪个可行呢? 非要从其中选择一个,本人选择2方案。不过建议最好还是换种实现方式 本帖最后由 wenyangzeng 于 2018-7-4 17:20 编辑
miraclexue 发表于 2018-7-4 16:23
此定时器主要目的是控制程序反复执行,您暂可不必注意这点,您看我提出的两个解决方案哪个可行呢? ...
何种方案都不应该关闭定时器,只要1个变量保存上次CNT值,与本次CNT比较即可。 oceane 发表于 2018-7-4 17:00
非要从其中选择一个,本人选择2方案。不过建议最好还是换种实现方式
感谢指教 wenyangzeng 发表于 2018-7-4 17:13
何种方案都不应该关闭定时器,只要1个变量保存上次CNT值,与本次CNT比较即可。 ...
感谢指教,为减少代码量,本人选择单脉冲模式,在定时器溢出后计数器自动停止计数(硬件自动清除CEN位),在中断最后再打开计数器(使能CEN位),这样可以确保每次都是从0开始计数。
对于定时器此种应用方式,主要是为了程序被中断保护,执行优先级高。
页:
[1]
2