我接下来要说的是我在做项目过程中在使用定时器时所遇到的问题进行总结,也想晒出来跟大家一起交流与分享!有说的不对的地方也请大家指教与谅解。
其实定时器有很多,跟不同微处理器所携带的定时器种类和个数有不同,我个人认为主要区分有两种: 一就是内核携带的系统节拍,也就是systick,就其功能来看与其他外围设备定时器没什么区别,但是就系统来看主要目的是为 RTOS 提供一个周期性中断,它中断处理程序并不需要清除 SysTick 中断源,当调用 SysTick 中断处理程序时,它将会由 NVIC 自动清除 SysTick 中断源。SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。该定时器的时钟源可以是内部时钟(FCLK),或者是外部时钟(STCLK信号)。不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。 还有就是我们经常使用到的定时器模块,一般都有提供 N 个 16 位的定时器/计数器,它们可以配置成用作独立的定时器或事件计数器,也可以用作一个 32 位的定时器或一个 32 位的实时时钟(RTC)。
其他就不多说了,因为大家都可能比较熟了,而我今天想留下的是一下几个问题:
一、我前段时间在用Cortex‐M3处理器的systick,在我看来我想让它实现每隔375us定时进入中断处理程序,中断里执行的程序的时间很短,就是启动一个无线模块的接收数据报文,问题出在了中断外,也就是外面死循环所要执行的程序功能有多个,分别是:
1、以太网数据接收;
2、串口数据接收与发送;
3、无线模块接收与处理;
一开始我没考虑太多,就按原先设计方案那样按时序编写代码,结果出现了一个令我头痛了很久的事件,首先是死循环里的程序,由于要处理的事件很多而定时器的时间很少(只有375us),因此在死循环的程序还没等执行完就被迫进入了中断,由于systick有个特点:Systick是一个递减的定时器,当定时器递减至0时,重载寄存器中的值就会被重装载,继续开始递减。STK_LOAD 重载寄存器是个24位的寄存器最大计数0xFFFFFF。也就是说当刚进入定时器中断那刻起,STK_LOAD 就已经 重载寄存器为定时值,执行中断子程序很短时间以后就跑出中断,要命的就是它不是从头开始执行,而是选择在上次没执行完的那里继续往下执行,这样呢我就郁闷了,整个程序跑来跑去没个准,用示波器就能看出来,程序完全不是按我原计划设计那样执行。嗨~~还是老老实实回到起点--看文档,经过一天的仔细研究发现还是自己缺少经验,以前也没用过定时器,最难搞的许多外围设备都被我搞定了总以为区区一个定时器应该没什么,所以也仔细研究过文档关于定时器的介绍,这次就吃亏了。所以我想给像我一样的初学者提点意见,中国的一句古话:磨刀不误砍柴功;说了那么多闲话,接下来我们继续往下谈,讲到这可能有过经验的高手就已经知道我程序出的问题了,问题就在死循环里的代码,后来经过整理我把各个功能以及之间的联系从头到尾梳理了一遍,在各个功能子程序的开始加了一条判断语句就解决问题了,比如:以太网接收,在开始我先判断是否有数据到,有则执行接收与处理,没有就退出执行其他语句;其他子程序以此处理,问题就迎刃而解了,现在你该知道问题所在了吧,哈哈~~~
|