像写Windows程序那样写单片机程序之多任务定时器 收藏

上传人:ji****72 文档编号:37605339 上传时间:2018-04-19 格式:DOC 页数:16 大小:88.50KB
返回 下载 相关 举报
像写Windows程序那样写单片机程序之多任务定时器 收藏_第1页
第1页 / 共16页
像写Windows程序那样写单片机程序之多任务定时器 收藏_第2页
第2页 / 共16页
像写Windows程序那样写单片机程序之多任务定时器 收藏_第3页
第3页 / 共16页
像写Windows程序那样写单片机程序之多任务定时器 收藏_第4页
第4页 / 共16页
像写Windows程序那样写单片机程序之多任务定时器 收藏_第5页
第5页 / 共16页
点击查看更多>>
资源描述

《像写Windows程序那样写单片机程序之多任务定时器 收藏》由会员分享,可在线阅读,更多相关《像写Windows程序那样写单片机程序之多任务定时器 收藏(16页珍藏版)》请在金锄头文库上搜索。

1、像写 Windows 程序那样写单片机程序之多任务定时器 收藏 最近失业在家心情郁闷,想想又很久没更新了,把这个相对比较“复杂”的多任务定 时器写写吧,之前在 csdn 的帖子里(单片机 C 语言程序该这样写!不是教科书上教的那 样!)就是用的这个定时器来支持我的论点的。又经过了一段时间的使用锤炼,基本可以 拿出来献丑一下了。定时器究竟有多重要?之前我也没有什么直观的感觉,似乎也就那么回事。不就一个中 断吗,还能如何?自从我看了C 语言嵌入式系统编程修炼之道这篇文章,才知道自己 之前多幼稚。我引用一下文章里关于定时器重要性的描述:(1)没有定时器,一个操作系统将无法进行时间片的轮转,于是无法进

2、行多任务的调度, 于是便不再成其为一个多任务操作系统; (2)没有定时器,一个多媒体播放软件将无法运作,因为它不知道何时应该切换到下一帧 画面; (3)没有定时器,一个网络协议将无法运转,因为其无法获知何时包传输超时并重传之, 无法在特定的时间完成特定的任务。因此,没有定时器将意味着没有操作系统、没有网络、没有多媒体,这将是怎样的黑暗?所以,合理并灵活地使用各种定时器,是对一个软件人的最基本需求! 怎么样?对定时器是不是又有了新的认识?可是,说了这么一大堆定时器的重要性,和我们需要挣钱吃饭买车买房娶老婆而为老板打 工而写的代码之间有什么关系?当然有了,唯物辩证法告诉我们,任何两个事物之间都有

3、联系,只不过联系的紧密程度不同而已-_-这个问题其实又回到了我们对单片机资源的封装 目的。我们为什么要封装单片机资源?为了模块化、为了结构清晰、为了可以复用这 些都没错,如果往关系到自己切身利益的方面去说目的,那就是-节省开发时间。没错, 一次封装好后,以后再使用就非常简单,无需每次都要从“轮子造起” 。而且,封装好的模 块,经过一段时间使用,bug 也很少,或者说几乎没有。用起来也很放心,至少出了问题 后,可以首先怀疑模块外的地方。节省下时间后,就不用总是加班,可以陪陪老婆孩子、 看看电视何乐而不为呢?这篇文章要是高考作文,估计阅卷老师看到这里就已经注定不及格了,竟然现在还没 进入主题。好了

4、,下面开始不及格作文的后半部分。有过单片机开发经验的人几乎都碰到过这样的需求:需要多个不同定时任务轮流执行。 我们会很直觉地这样实现:定义若干个全局计数器变量,为每个变量设置一个超时计数值, 然后把每个变量在一个定时中断中逐次累加(或递减),直到某个变量超过设定的超时计数 值,从而判断不同的到时任务。这样做的优点就是容易实现,比较直观。但是缺点还是比较明显的,只要有这种多定时任 务需求就需要重复这么一次,浪费了不少重复编码的时间。更主要的是,定时中断中不仅 仅要处理真正的业务逻辑流程,还要处理这些定时计数变量,实现起来比较凌乱。写程序 很忌讳同时实现很多其实不相干的功能,这样会增加脑力负担,也

5、不容易写出优质的代码。让我们跳出这个“常规”的方法,重新审视一下。我们的需求就是:可以设置多个不 同时间间隔的定时任务,到时就唤醒。就这么一句话,非常简单,而且也十分明确。假如,有三个定时任务 a,b,c 分别是 5ms、10ms 和 15ms。如果我们在模块内部启动一 个 5ms 的定时器,再定义三个计数器变量 t1,t2 和 t3 分别表示三个定时任务。那么,每当 定时器到时一次,t1、t2、t3 分别减 1,那么谁减到 0 则表示对应的定时任务到时了。这明显是“常规”方法的翻版嘛。是的,没错。我们再继续思考一下,如果有定时任 务中途取消,又有新的任务加入怎么办?我们注意到了,所有的定时任

6、务在最小的时间片 内都需要重新计算计数变量的值。所以就可以想到,把所有的计数变量都放到统一的“容 器”中,然后每当最短的定时中断到时后,就依次把“容器”中的所有变量都减 1。如果 有新的任务加入,那就在“容器”中再分配一个变量,如果有取消的任务,那就在“容器” 中删除一个变量。不知不觉,整个功能的模型就已经出炉了。剩下的就是开始动手实现了。依然是先看一下头文件:view plaincopy to clipboardprint?102030405060708090 100110120130140150 #ifndef _TIMER_CONFIG_H_ #define _TIMER_CONFIG_

7、H_ #include “c51basedef.h“ #include “oscfrequencydef.h“ #ifndef OSC_FREQUENCY #error undefined OSC_FREQUENCY #endif /#warning must be used in AT89C52 or later version because of “idata“ #warning * * #warning ! make sure MAX_TIMER_EVENT_NUM and TIMER0_BASE_INTERVAL has appropriate value! #warning * *

8、 /#define MICROSECOND_LEVEL_TIMER /微秒单位 #define MILLISECOND_LEVEL_TIMER /毫秒单位 #ifndef MICROSECOND_LEVEL_TIMER #ifndef MILLISECOND_LEVEL_TIMER #error !must define MICROSECOND_LEVEL_TIMER or MILLISECOND_LEVEL_TIMER identifier! #endif #endif #ifdef MICROSECOND_LEVEL_TIMER #ifdef MILLISECOND_LEVEL_TIMER

9、 #error !ONLY ONE identifier can be defined! #endif #endif /* 定时中断每 TIMER0_BASE_INTERVAL 毫秒产生一次,用户定义的中断时间必须是它的 整数倍 */ #define MAX_TIMER_EVENT_NUM 3 /可设置不同定时事件的最大个数 #define TIMER0_BASE_INTERVAL 25 /单位:毫秒或微秒,注意不要超过定时 器的溢出上限,如 12MHz 晶振的溢出上限是 65.535ms typedef void (*TIMERPROC)(BYTE nID); void InitTimer0

10、(); BOOL SetTimerCallback(TIMERPROC lpTimerFunc); /必须在 SetTimer0 之前调用 BOOL SetTimer0(BYTE nID, WORD wInterval); /通过 nID(nID0)来区分 /BOOL KillTimer0(BYTE nID); 节省 rom,暂不用 / /以下为内部使用 typedef struct tagTIMERINFO BYTE nID; /定时器 ID WORD wInterval; /此定时器的设定间隔时间 WORD wElapse; /剩余的时间 TIMERINFO; static BOOL Ad

11、dTail(const TIMERINFO* pTimerInfo); static BOOL Remove(BYTE nID); static BYTE FindIDIndex(BYTE nID); #endif #ifndef _TIMER_CONFIG_H_ #define _TIMER_CONFIG_H_ #include “c51basedef.h“ #include “oscfrequencydef.h“#ifndef OSC_FREQUENCY #error undefined OSC_FREQUENCY #endif/#warning must be used in AT89C

12、52 or later version because of “idata“ #warning * * #warning ! make sure MAX_TIMER_EVENT_NUM and TIMER0_BASE_INTERVAL has appropriate value! #warning * */#define MICROSECOND_LEVEL_TIMER /微秒单位 #define MILLISECOND_LEVEL_TIMER /毫秒单位#ifndef MICROSECOND_LEVEL_TIMER #ifndef MILLISECOND_LEVEL_TIMER #error

13、!must define MICROSECOND_LEVEL_TIMER or MILLISECOND_LEVEL_TIMER identifier!#endif#endif#ifdef MICROSECOND_LEVEL_TIMER #ifdef MILLISECOND_LEVEL_TIMER #error !ONLY ONE identifier can be defined! #endif#endif/* 定时中断每 TIMER0_BASE_INTERVAL 毫秒产生一次,用户定义的中断时间必须是它的 整数倍 */ #define MAX_TIMER_EVENT_NUM 3 /可设置不同定时事件的最大个数 #define TIMER0_BASE_INTERVAL 25 /单位:毫秒或微秒,注意不要超过定时器 的溢出上限,如 12MHz 晶振的溢出上限是 65.535mstypedef vo

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号