打印
[STM32F1]

关于stm32f103中的TIM定时器的bug现象总结?

[复制链接]
3783|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 摩天轮1111 于 2015-8-11 14:26 编辑

        最近练习使用TIM定时器作为延时的时钟来使用,但是发现TIM定时器好像是有bug呢?还是怎么搞的,我先说下我的思路,
        main函数里面while(1)死循环,一直等待,
       开启了外部触发中断,EXTI1, 其中EXTI1中断服务函数里面有个delay(ms),
       然后这个ms就是和TIM关联的,也就是ARR的值,然后delay里面是while(flag)(flag初值为1,且delay函数最后一句话会重置flag为1)
       在TIM的中断服务函数里面去把flag清0达到退出delay延时函数的目的,这样的思路
下面就是比较奇葩的问题了,首先把几个关键函数列上来

下面说说情况,
1.如果设置的TIM中断的优先级高于EXTI1的话,显然在EXTI 的中断服务函数里面的delay(2000)会延时2秒,我看串口显示的话,先看到ok,然后过了2秒看到you have already ,,,,,就知道这个delay(2000)执行了,实际的情况也是这样。

2.但是如果我设置的TIM的抢占优先级低于EXTI的话,实际运行的效果是,ok之后瞬间就输出you have ,,,,,,这串代码,这说明程序肯定经历了delay(2000)也肯定进去了TIM的中断服务函数,因为flag只有在那里才能变成0,然后也就是说TIM没有等2000ms,应该是立马就进入了中断服务函数,但是问题是优先级在这呢,为什么能进得去?

3.如果我设置的TIM中断服务函数里面,进入中断就关闭计数器,然后在delay里面开启计数器,那么这个时候,TIM的优先级低的话,delay(2000)是过不去的,也就是没法进入TIM的中断服务函数,如果TIM抢占优先级高的话,那是可以进入的,delay(2000)可以执行过去

4.TIM的中断,好像是一开计数,就会立马进入中断,如我TIM配置的程序里面,首先对TIM的SR的第0位清除了,也就是清除了更新标志位,这样的时候全速跑的话,配置完TIM应该是没有进入TIM中断服务函数的,不然flag为0,那个delay(4000)不会等4s,如果没有那个清除位,那么一全速跑,完全是第一步就进入TIM中断了,而且还发现这个第一部进中断的问题,他是不执行完TIM的中断服务函数里面的所有的内容,只执行到flag等于0这一句(看现象判断出来的因为它不打印TIM中断服务里面的数,jlink单步调试完全没有逻辑)

5.但是问题又来了,全速运行是不会配置完就近TIM的中断服务函数,而我进行jlink单步运行,它还是会配置完TIM之后,就立马进入TIM的中断服务函数,很奇葩,基本可以说在TIM的定时器的debug中,单步运行和全速跑都没有一样的情况,很不相符, 15 外部触发中断 timer中断嵌套实验.rar (288.98 KB)




沙发
摩天轮1111|  楼主 | 2015-8-11 14:00 | 只看该作者
我现在总结的现象就是,除非在TIM的中断服务函数里面关闭计时器,需要用它定时的时候再打开,否则当TIM的中断优先级低于EXTI1的优先级时候,在执行EXTI1中断服务函数的时候,TIM中断服务函数还是可以进入的,但是不会完全执行完,执行一两句就结束了,如果设置TIM中断优先级高于EXTI1那么就一切正常,这应该是芯片自己的bug吧?

使用特权

评论回复
板凳
摩天轮1111|  楼主 | 2015-8-11 14:09 | 只看该作者
刚刚又把TIM3 IRQ Handler中的flag=0放到最后了,也是很奇葩,在EXTI1中,ok输出之后,就输出you have already,,,,,这串字符,意味着delay(2000)瞬间过去了,说明flag被清0了,但是还没有执行TIM中断服务函数里面的printf等等的这些函数,好奇怪,

使用特权

评论回复
地板
摩天轮1111|  楼主 | 2015-8-11 14:25 | 只看该作者
我现在感觉甚至这个是编译器的问题了不是其他的什么问题了,这个真是搞的我头大了,,,,

使用特权

评论回复
5
myxiaonia| | 2015-8-11 14:50 | 只看该作者
好水的问题  总结现象即可  你的问题只要描述就可以解决了   因为比较初级


你自己都说tim中断优先级高就可以了  为何还要搞低  

使用特权

评论回复
6
摩天轮1111|  楼主 | 2015-8-11 16:02 | 只看该作者
本帖最后由 摩天轮1111 于 2015-8-11 17:36 编辑
myxiaonia 发表于 2015-8-11 14:50
好水的问题  总结现象即可  你的问题只要描述就可以解决了   因为比较初级

呵呵,请您多思考思考,搞低出现的现象是不是和逻辑不相符?,搞高行就不管了,,但是我做不到,我很好奇为什么搞低就有问题,而且和自己预想的逻辑不相符,ps另外您真的发现问题所在了吗?

使用特权

评论回复
7
摩天轮1111|  楼主 | 2015-8-11 17:34 | 只看该作者
找到问题的根结了,一个也不算隐蔽的程序bug,标题纯属吸引人眼光而已,这个问题困扰我很久了,今天在朋友的帮助下,总算找到根结了,原因如下
在EXTI1中的delay(2000)当TIM的优先级低的时候还是能过去,说明delay过去了,flag被置为0了,但是为什么是0呢,因为在主函数里面输出www.那段代码之后,我没有关闭TIM的计数器(上面也说了,如果关闭就没问题了),这时候还是会继续隔着4秒进入一次TIM中断,进入一次中断之后,就会把flag变成0了,然后却没有delay让flag变回1,也就是从此开始flag就是0了,所以进入EXTI1里面的delay(2000)时候flag就是0,肯定瞬间就跳出delay,也没有执行TIM中断里面的东西,也就是不打印出来东西,

正常的话如果EXTI1里面执行了TIM的中断的话,会输出printf的东西,所以这里flag变成0除了TIM中断服务函数能将它变成0其他的没有函数可以了,但是在EXTI1里面的执行delay的时候的flag为0并不是EXTI1里面执行的时候才变成0的,是在进入EXTI1之前就已经是0了,
程序bug,不算隐蔽,但是也是一些容易忽略的,这种问题可以通过在delay上面多加一句flag=1,如下图所示解决

但是这样也是有bug的,出现的概率太小太小的,但是还是会有可能的,所以编程的好习惯和通用思路还是要养成和学习的,有些问题是传统问题的话,有些固有思路还是要学习学习的,我这里的程序完全是验证中断嵌套的,耍耍玩的,高手莫笑,莫喷,只是针对这么个简单的循环嵌套验证程序里的多种尝试时候出现的一些貌似反常现象的探究而已,

使用特权

评论回复
8
ninxin| | 2022-5-31 10:39 | 只看该作者
上面加“delay上面多加一句flag=1,.......”,恒等跳不出来循环,你是不是在带节奏?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

38

主题

224

帖子

15

粉丝