一大早我爬起来了,很高兴,没用多少 时间就搞定了定时器3,当然之前花了很长的时间,不断的做实验,芯片烧了不下百次了.所以我很高兴,以为红外的问题可以用定时器彻底解决了,可惜啊可惜,问题总是接连不断的挑战我.
我定义了两个全局的计数变量sCount,eCount,让sCount不断在中断里累加,然后跳到后台进行比较,本来吧,这个问题不是问题,应该可以很顺利通过,可是这个就是问题,sCount不断的加上去,没有停过,我用断点调试,发现sCount的值在累加,但是没有去和eCount去比较,程序明明是这样写的呀,怎么没有去执行呢?
没办法,打开汇编看一下,问题出来了,确实没有比较,而且这两个变量时xdata类型,要用外部指针访问地址,会不会访问的时候出错呢?
google了一下,发现了一些对变量常用的修饰符,其中有一个从来没用过,就是volatile.我这种问题称为异步访问变量,此种变量必须恰当定义并有足够的保护,而volatile这个关键字就是防止编译器对变量的优化,遵守源代码给出的变量访问方式并保证该变量在每个"顺序点"是稳定的,理论的东西我不想讲太多,反正出了这种问题是会让你感觉很莫名其妙的.你感觉应该按你的程序逻辑运行下去的,但是它就是不遵守你的规则.
当你访问这一类型的变量时,其实访问到的是先前的值和更新的值的混合体,在主线程里会使得程序出乱子的.如果你运气好就通过了,如果像我这种运气背的就死活停止那里,当然就出来这篇文章了.
下面我说说解决方法吧,思想就是当你获取这个变量时要先把内存保护起来,一种方法上面说过了,就是用volatile关键字修饰.另一种方法是用一个监视函数,这个我还是第一次碰到,也许以前编程的时候也用到,但是没有这次有针对性.
__monitor uint16 get_sCount ()
{ return sCount;}只要调用这个函数就可以获取到sCount了
监视函数能够在运行时屏蔽中断,在结束时恢复先前的中断状态。
这个问题还是和编译器有关的,我现在用的是IAR,也许其他编译器会自动帮你搞定,不管怎样,也学到一点的
两种方法我都试过了,感觉用监视函数会更适合现在的程序,因为出来的波形很精确,可以说搞定了
帮朋友网站做个外链