|
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统 驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe |
精品程序:利用T2扩展多个软件定时器,彻底解决定时器不够用的问题 |
作者:LPC900 栏目:单片机 |
/* SoftTimer.h 利用定时器T2模拟多个软件定时器 作者:21icbbs LPC900,2005-08 特点: 只占用一个硬件定时器T2,就可以扩展出多达数十个以上的软件定时器 软件定时器基本定时单位是10ms,定时范围很宽:0.01~163.84s 软件定时器数量可以按需要设定,每增加一个,只多消耗2个字节的RAM空间 利用定时器T2的自动重装特性,能够实现所有软件定时器的精确定时 所有软件定时器都工作在14位倒计时方式,用TR和TF位控制,使用极为方便 第0号定时器专门用于Delay()函数,其它定时器可供用户程序自由使用 */ #ifndef _SOFT_TIMER_H_ #define _SOFT_TIMER_H_ #include <REG52.H> //定义软件定时器数量(至少1个) #define TIMER_N 8 //定义时钟频率(单位:Hz) #define MCLK 11059200L //定义软件定时器结构 //每个定时器只占用2个字节 struct { volatile unsigned TR:1; //起停标志,0-停止运行,1-开始运行 volatile unsigned TF:1; //溢出标志,0-未溢出,1-溢出 volatile unsigned TV:14; //14位定时值 }idata Timer[TIMER_N]; //软件定时器初始化 void TimerInit() { unsigned int x; unsigned CHAR i; EA = 0; for ( i=0; i<TIMER_N; i++ ) { Timer[i].TR = 0; Timer[i].TF = 0; Timer[i].TV = 0; } T2CON = 0x00; x = (unsigned int)(MCLK / 1200L); #if ( (MCLK % 1200L) >= 600L ) x++; #endif x = 0 - x; RCAP2L = (unsigned CHAR)x; RCAP2H = (unsigned CHAR)(x >> 8); TL2 = RCAP2L; TH2 = RCAP2H; ET2 = 1; TR2 = 1; EA = 1; } /* 函数:TimerOn() 功能:启动定时器 参数: n:定时器序号 t:定时器初值,取值0~16383 t>0时,定时(0.01*t)s t=0时,定时163.84s */ void TimerOn(unsigned CHAR n,unsigned int t) { Timer[n].TR = 0; Timer[n].TF = 0; Timer[n].TV = t; Timer[n].TR = 1; } /* 函数:TimerOff() 功能:关闭定时器 参数: n:定时器序号 */ void TimerOff(unsigned CHAR n) { Timer[n].TR = 0; Timer[n].TF = 0; } /* 函数:T2_INTR_SVC() 功能:定时器T2中断服务函数,每10ms中断1次 */ void T2_INTR_SVC() interrupt 5 { unsigned CHAR i; TF2 = 0; for ( i=0; i<TIMER_N; i++ ) { if (Timer[i].TR) { if ( --Timer[i].TV == 0 ) { Timer[i].TF = 1; } } } } /* 函数:Delay() 功能:延时0.01~163.84s 参数: t:延时参数,取值0~16383 t>0时,延时(0.01*t)s t=0时,延时163.84s */ void Delay(unsigned int t) { TimerOn(0,t); for (;;) { PCON |= 0x01; if (Timer[0].TF) { TimerOff(0); break; } } } #undef TIMER_N #undef MCLK #endif //_SOFT_TIMER_H_ * - 本贴最后修改时间:2005-8-20 16:19:11 修改者:LPC900 |
2楼: | >>参与讨论 |
作者: hotpower 于 2005/8/20 16:53:00 发布:
色彩不错就是费时 多个计数器是可以从一个基计数器推出的... |
3楼: | >>参与讨论 |
作者: sb_L 于 2005/8/20 17:57:00 发布:
对于资源有限的芯片,N年前就这样了!只是用的是ASM |
4楼: | >>参与讨论 |
作者: athlon64fx 于 2005/8/20 18:25:00 发布:
为什么非要用个这么麻烦的数据结构呢? 把简单的问题复杂化了。一切都要尽可能地简单! |
5楼: | >>参与讨论 |
作者: hiberhe 于 2005/8/20 19:58:00 发布:
用数据结构其实是简单了:) 软件定时器肯定是要用的. 数据结构的方式看起来结构重合理,也更方便.楼主的程序风格不错! 如果RAM足够的话,就可以不用位域,(多耗两个字节),速度会快些,定时也可长些. 另外, struct { volatile unsigned TR:1; //起停标志,0-停止运行,1-开始运行 volatile unsigned TF:1; //溢出标志,0-未溢出,1-溢出 volatile unsigned TV:14; //14位定时值 }idata Timer[TIMER_N]; 我喜欢这样用 typedef struct { volatile unsigned TR:1; //起停标志,0-停止运行,1-开始运行 volatile unsigned TF:1; //溢出标志,0-未溢出,1-溢出 volatile unsigned TV:14; //14位定时值 }TIMER, *PTIMER; TIMER idata Timer[TIMER_N]; 同时: for ( i=0; i<TIMER_N; i++ ) { Timer[i].TR = 0; Timer[i].TF = 0; Timer[i].TV = 0; } 也喜欢写成这样 for (i = 0; i < sizeof(TIMER)*TIMER_N; i++) { ((unsigned CHAR idata*)&Timer)[i] = 0; } 或者偷懒时就写成 #include <string.h> // ....... memset((void *)&Timer,0x00,sizeof(TIMER)*TIMER_N); |
6楼: | >>参与讨论 |
作者: yadog 于 2005/8/20 21:09:00 发布:
re 学习 |
7楼: | >>参与讨论 |
作者: ketp 于 2005/8/21 8:18:00 发布:
大家肯定都在用 只是方法不同,lz的实现方法逻辑清晰,但资源占用就多了点. |
8楼: | >>参与讨论 |
作者: faucon 于 2005/8/21 10:54:00 发布:
Re 色彩不错啊 |
9楼: | >>参与讨论 |
作者: LPC900 于 2005/8/22 16:08:00 发布:
往上顶 |
10楼: | >>参与讨论 |
作者: wayner 于 2005/8/23 17:45:00 发布:
请教斑竹:结构定义里面怎么可以写“unsigned TR:1;”? 疑问①unsigned后面没有数据类型声明,缺省是int? ②TR后面加“:1”是什么意思?我怎么看认为c语法有问题?(从没看到过这样写) ③从后面推测TR、TF是位变量,TV是int变量,是吗? 写得不对,请见谅! |
11楼: | >>参与讨论 |
作者: computer00 于 2005/8/23 18:04:00 发布:
TR后面加“:1”表示位段。去看看C语言的位段吧。 |
12楼: | >>参与讨论 |
作者: pantodd 于 2005/8/23 18:11:00 发布:
这段时间正在做多路脉冲检测。 可以学习了。四路脉冲而使用的89C52只有三个定时器。谢谢 |
13楼: | >>参与讨论 |
作者: LPC900 于 2005/8/23 19:05:00 发布:
可以跑定时多任务程序 举例: #include "SoftTimer.h" #include "Task.h" //自行定义的多任务头文件 void main() { TimerInit(); TimerOn(1,1); TimerOn(2,1); ... while (1) { PCON |= 0x01; //节电 if ( Timer[1].TF ) { Task01(); //注意:不能包含有死循环 TimerOn(1,10); } if ( Timer[2].TF ) { Task02(); //注意:不能包含有死循环 TimerOn(1,85); } ... } } |
14楼: | >>参与讨论 |
作者: LPC900 于 2005/8/23 19:09:00 发布:
如果谁不清楚位段(位域)的话,建议回去读读谭浩强的C语言教程 |
15楼: | >>参与讨论 |
作者: toonaive 于 2005/8/24 11:01:00 发布:
请教搂住 为什么用 #if ( (MCLK % 1200L) >= 600L ) x++; #endif 而不用直接用 if ( (MCLK % 1200L) >= 600L ) x++; 还有 #undef TIMER_N #undef MCLK 有什么用意? 谢谢 |
16楼: | >>参与讨论 |
作者: stintair 于 2005/8/24 16:00:00 发布:
路过,关注一下 —— |
17楼: | >>参与讨论 |
作者: hiberhe 于 2005/8/27 22:00:00 发布:
用条件编译的话,不满足条件,不包含代码 如果用if判断的话,总会在程序中有那么不段,不管满足条件不. #undef的意思就是从这以后,取消对其的定义,这样以后的程序又可以重新对其进行定义和使用了. |
18楼: | >>参与讨论 |
作者: hunter01 于 2005/8/28 1:27:00 发布:
还没有查询系统时间简单! * - 本贴最后修改时间:2005-8-28 10:58:38 修改者:hunter01 |
|
|
免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入 |
Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号 |