📄 timer.c
字号:
/*********************************************************************
*Copyright-(c) 2003, *
*All rights reserved. *
* *
* 文件名称: TIMER.C *
* 摘要 : For 80x86 *
* *
* 当前版本: 2.3 *
* 作者 : Liy-tj *
* 完成日期: 2006年2月23日 *
* 修改 : 1、把在中断内调用任务函数功能作为可裁减功能,可以通过头 *
* 文件中的TMR_INTR_FNCT_EN来裁减。 *
* *
* 当前版本: 2.2 *
* 作者 : Liy-tj *
* 完成日期: 2005年4月15日 *
* 修改 : 1、修改了TMR_Delete()函数,增加对ptmrid指针是否为NULL的*
* 判断。 *
* *
* 取代版本: 2.1 *
* 作者 : Liy-tj *
* 完成日期: 2005年3月3日 *
* 修改 : 1、加入获取计数值函数TMR_GetCtr(),用于实时获取定时器的*
* 计数值。 *
* *
* 取代版本: 2.0 *
* 作者 : Liy-tj *
* 完成日期: 2004年9月29日 *
* 修改 : 1、将系统节拍TMR_TICK_LENGTH的单位由毫秒变为微秒,从而 *
* 使计时器的定时范围可以小于1毫秒。但在编程时注意,系 *
* 统节拍不应太短,使系统负载过大; *
* 2、定时长度的单位由原先统一的毫秒,改为可在微秒、毫秒和*
* 秒之间选择,以免在长时间定时时,数据过大而溢出。 *
* *
* 取代版本: 1.2 *
* 作者 : Liy-tj *
* 完成日期: 2004年9月20日 *
* 修改 : 1、对模块内的函数进行重新命名,采用"模块名_函数名"的格 *
* 式,以期与其他模块统一; *
* 2、将全局变量的定义放到头文件中; *
* 3、修改TMR_Reload()的工作方式,使其在复位计时器计数值后*
* 让计时器开始运行; *
* *
* 取代版本: 1.1 *
* 作者 : Liy-tj *
* 完成日期: 2003年10月22日 *
* 修改 : 1、将计时器数据结构由结构体改为数组,提高代码效率; *
* 2、增加计时器工作模式属性,包含CONT(连续)、ONCE(单次) *
* 和DELAY(延时)模式; *
* 3、增加了LongDelay()函数,用以实现数毫秒到几十秒范围的 *
* 延时,若使用TMR_LARG_RANG模式,延时长达数天; *
* 4、定义了计时器中断使用的寄存器组常数,可以根据中断函 *
* 数设定TmrIntTask()函数使用的寄存器组。 *
* 5、修改了TmrDelet()函数,传入计时器id的指针,在删除计 *
* 时器后,将计时器id赋为TMR_MAX; *
* *
* 取代版本: 1.0 *
* 作者 : Liy-tj *
* 完成日期: 2003年9月22日 *
* 修改 : 1、计时器计时范围分为两档,小范围为0~65,535,大范围为 *
* 0~4,294,967,295,通过宏定义TMR_LARG_RANG进行选择。 *
* 2、完善了TmrInit()函数,对计时器参数都进行了初始化; *
* 3、对计时器函数进行修改的程序段都放入临界区,防止中断进*
* 入,发生冲突; *
* 4、修改了TmrDelet()函数,传入计时器指针的指针,在删除计*
* 时器后,将计时器指针指向空; *
* 5、在大部分函数中添加了计时器指针非空判断,以免发生误操*
* 作; *
* 6、将定时计数单位统一为毫秒,取消TmrSetMST()函数。 *
* *
* 取代版本: 0.4 *
* 作者 : Liy-tj *
* 完成日期: 2003年9月5日 *
* 修改 : 1、增加了两个函数(宏定义),分别是TmrCallIntFnct()和 *
* TmrCallFnct(),用于直接调用关联函数,并且将计时器重 *
* 置,重新开始计时。 *
* *
* 取代版本: 0.3 *
* 作者 : Liy-tj *
* 完成日期: 2003年8月31日 *
* 修改 : 1、不再使用分配动态内存方式创建新计时器,而是在程序运 *
* 开始处根据最多计时器数量来定义计时器数组,将计时器 *
* 分配到静态内存中; *
* 2、分别由工作计时器链表和空闲计时器链表来管理计时器模 *
* 块; *
* 3、新创建的计时器插入到工作链表的首部,而删除的计时器 *
* 则被插入到空闲计时器链表的尾部。 *
* *
* 取代版本: 0.2 *
* 作者 : Liy-tj *
* 完成日期: 2003年8月29日 *
* 修改 : 1、取消触发标志结构体,将标志添加到计时器结构体中; *
* 2、计时器操作函数不再通过标志结构体来获取计时器地址; *
* 3、在计时器结构体中增加的一个函数指针,两个函数指针分 *
* 别用于指向中断内运行函数和中断外运行函数; *
* 4、计时器溢出后,若指向中断内运行函数指针非空,则直接 *
* 调用函数;反之,将触发标志置位; *
* *
* 取代版本: 0.1 *
* 作者 : Liy-tj *
* 完成日期: 2003年8月28日 *
*********************************************************************/
#define TMR_GLOBALS
#include "includes.h"
/*********************************************************************
* 初始化计时器模块 *
* *
* 功能描述 : 对计时器数组进行初始化,在程序开始时调用。 *
* *
* 输入参数 : 无 *
* 返回参数 : 无 *
* 文件名称 : TIMER.C *
* 作者 : Liy-tj *
*********************************************************************/
void TMR_Init(void)
{
TMR_ID tmrid = 0;
OS_ENTER_CRITICAL();
for(; tmrid<MAX_TMR; tmrid++)
{
TmrSta[tmrid] = 0;
TmrInit[tmrid] = 0;
TmrCtr[tmrid] = 0;
TmrFnct[tmrid] = NULL; //指向在中断过程外运行的函数的指针
#ifdef TMR_INTR_FNCT_EN
TmrIntFnct[tmrid] = NULL; //指向在中断过程中运行的函数的指针
#endif
}
OS_EXIT_CRITICAL();
}
/**********************************************************************
* 获取一个空计时器 *
* *
* 功能描述 : 这个函数计时器数组中获取一个空计时器,并返回计时器 *
* id。 *
* *
* 输入参数 : 无 *
* 返回参数 : tmrid 计时器的编号 *
* 文件名称 : TIMER.C *
* 作者 : Liy-tj *
**********************************************************************/
TMR_ID TMR_GetFree(void)
{
TMR_ID tmrid = 0;
while((TmrSta[tmrid]&TMR_EN) && (tmrid < MAX_TMR))
{
tmrid++;
}
return (tmrid);
}
/**********************************************************************
* 创建一个计时器 *
* *
* 功能描述 : 这个函数创建一个新计时器。并且根据输入的参数对计时 *
* 器进行初始化。 *
* *
* 输入参数 : tmrinit 计时器计时长度 *
* tmrunit 计时器计时长度单位,微秒:UNIT_US *
* 毫秒:UNIT_MS *
* 秒 :UNIT_S *
* tmrmod 计时器工作模式 *
* intfnct 指向中断内调用函数的指针 *
* fnct 指向中断外调用函数的指针 *
* 返回参数 : tmrid 创建的计时器的id *
* 文件名称 : TIMER.C *
* 作者 : Liy-tj *
**********************************************************************/
#ifdef TMR_LARG_RANG
TMR_ID TMR_Create(INT32U tmrinit, INT8U tmrunit, INT8U tmrmod,
void (*intfnct)(void), void (*fnct)(void))
#else
TMR_ID TMR_Create(INT16U tmrinit, INT8U tmrunit, INT8U tmrmod,
void (*intfnct)(void), void (*fnct)(void))
#endif
{
TMR_ID tmrid = TMR_GetFree();
if(tmrid < MAX_TMR)
{
if((tmrmod != TMR_MOD_CONT)&&(tmrmod != TMR_MOD_ONCE)
&&(tmrmod != TMR_MOD_DELAY))
{
tmrid = MAX_TMR;
}
else
{
OS_ENTER_CRITICAL();
TmrSta[tmrid] = 0x01;
TmrSta[tmrid] |= tmrmod;
TMR_SetLen(tmrid, tmrinit, tmrunit);
TmrFnct[tmrid] = fnct;
#ifdef TMR_INTR_FNCT_EN
TmrIntFnct[tmrid] = intfnct;
#endif
OS_EXIT_CRITICAL();
}
}
return (tmrid);
}
/*********************************************************************
* 开始一个计时器 *
* *
* 功能描述 : 这个函数使一个计时器开始计数。 *
* *
* 输入参数 : tmrid 计时器id *
* 返回参数 : 无 *
* 文件名称 : TIMER.C *
* 作者 : Liy-tj *
*********************************************************************/
void TMR_Start(TMR_ID tmrid)
{
if((tmrid < MAX_TMR)&&((TmrSta[tmrid]&TMR_EN)==1)) //计时器已经创建
{
OS_ENTER_CRITICAL();
TmrSta[tmrid] |= TMR_RUN;
TmrSta[tmrid] &= TMR_FLG_DOWN;
OS_EXIT_CRITICAL();
}
}
/*********************************************************************
* 停止一个计时器 *
* *
* 功能描述 : 这个函数使一个计时器停止计数。 *
* *
* 输入参数 : tmrid 计时器id *
* 返回参数 : 无 *
* 文件名称 : TIMER.C *
* 作者 : Liy-tj *
*********************************************************************/
void TMR_Stop(TMR_ID tmrid)
{
if(tmrid < MAX_TMR)
{
OS_ENTER_CRITICAL();
TmrSta[tmrid] &= TMR_STOP;
TmrSta[tmrid] &= TMR_FLG_DOWN;
OS_EXIT_CRITICAL();
}
}
/*********************************************************************
* 重载计时器 *
* *
* 功能描述 : 这个函数使计时器的计数器重新开始计数。 *
* *
* 输入参数 : tmrid 计时器id *
* 返回参数 : 无 *
* 文件名称 : TIMER.C *
* 作者 : Liy-tj *
*********************************************************************/
#ifdef TMR_RELOAD_EN
void TMR_Reload(TMR_ID tmrid)
{
if(tmrid < MAX_TMR)
{
OS_ENTER_CRITICAL();
TmrCtr[tmrid] = TmrInit[tmrid];
TmrSta[tmrid]|= TMR_RUN;
TmrSta[tmrid]&= TMR_FLG_DOWN;
OS_EXIT_CRITICAL();
}
}
#endif
/**********************************************************************
* 修改计时器计时长度 *
* *
* 功能描述 : 修改计时器计时长度。 *
* *
* 输入参数 : tmrid 计时器id *
* tmrinit 计时长度 *
* tmrunit 计时器计时长度单位,微秒:UNIT_US *
* 毫秒:UNIT_MS *
* 秒 :UNIT_S *
* 返回参数 : 无 *
* 文件名称 : TIMER.C *
* 作者 : Liy-tj *
**********************************************************************/
#ifdef TMR_LARG_RANG
void TMR_SetLen(TMR_ID tmrid, INT32U tmrinit, INT8U tmrunit)
#else
void TMR_SetLen(TMR_ID tmrid, INT16U tmrinit, INT8U tmrunit)
#endif
{
INT32U inittemp; //计算定时长度的中间变量
if(tmrid < MAX_TMR)
{
switch(tmrunit)
{
case UNIT_MS: //定时单位为毫秒
inittemp = (INT32U)(((FP64)tmrinit/TMR_TICK_LENGTH)*1000+0.5)-1;
break;
case UNIT_S: //定时单位为秒
inittemp = ((INT32U)((FP64)tmrinit*(1000000.0/TMR_TICK_LENGTH)+0.5))-1;
break;
default: //缺省定时单位为微秒
inittemp = (INT32U)((FP64)tmrinit/TMR_TICK_LENGTH+0.5)-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -