/******************************************************************************
* 文件名称:SoftTimer.h
* 内容摘要:软件定时器模块头文件
* 其他说明:首先运行TimersInit函数,需向该函数提供"1ms的系统时钟"和"最大系统ms数",
* 然后在各自的应用模块中调用CreatTimer创建定时器,该函数返回的地址为该定
* 时器的地址,可用与重启或删除定时器结点,请妥善保管。请在主循环中执行
* ProcessTimer函数以更新定时器时间。
* 当前版本:V1.00
* 作 者: zgj
* 完成日期:2018年2月20日
文件资源下载:https://download.csdn.net/download/qq_26964063/12111597
******************************************************************************/
#ifndef __SOFTTIMER_H_
#define __SOFTTIMER_H_
#include "config.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_VALUE_32_BIT 0xFFFFFFFF /* 32bit最大ms数 */
#define SW_ERROR (-1) /* 操作失败返回值 */
#define SW_OK (0) /* 操作成功返回值 */
#define SINGLE 0
#define PERIOIC 1
typedef int (*TMRCALLBACK)(void *pArg); //定时回调函数指针
typedef unsigned int (*TMRSOURCE)(void); //系统时钟函数指针
/****************************************************
* 结构名:TIMER
* 描述: 软件定时器数据结构
* 参数:
uint8 periodic; SINGLE 单次触发
PERIOIC 周期触发
uint32 start; 0~0xFFFFFFFF 计时器起始时间
uint32 now; 0~0xFFFFFFFF 计时器当前时间
uint32 elapse; 0~0xFFFFFFFF 计时器已过时间
uint32 timeout; 0~0xFFFFFFFF 计时器计时时间
TMRCALLBACK pfTimerCallback; 计时结束后执行的回调函数
void *pArg; 回调函数的参数
* 作 者: zgj
* 完成日期:2018年2月20日
****************************************************/
typedef struct _TIMER
{
void *pArg; /* 回调函数的参数 */
uint8 periodic; /* 单次触发/周期触发 */
uint32 start; /* 计时器起始时间 */
uint32 now; /* 计时器当前时间 */
uint32 elapse; /* 计时器已过时间 */
uint32 timeout; /* 计时器计时时间 */
TMRCALLBACK pfTimerCallback; /* 计时结束后执行的回调函数 */
} TIMER;
/****************************************************
* 结构名:TIMER_TABLE
* 描述: 定时器列表(链表)
* 参数:
TIMER data; 本计时器结点数据
struct _TIMER_TABLE* next; 下一个定时器结点地址
* 作 者: zgj
* 完成日期:2018年2月20日
****************************************************/
typedef struct _TIMER_TABLE
{
TIMER data; /* 本计时器结点数据 */ //数据域
struct _TIMER_TABLE* next; /* 下一个定时器结点地址 */ //指针域
}TIMER_TABLE;
/*************************************************************************
* 函数名称:int TimersInit(TMRSOURCE pfTimer)
* 功能说明:初始化软件定时器模块
* 输入参数:TMRSOURCE pfTimer 系统1ms时钟函数
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
int TimersInit(TMRSOURCE pfTimer);
/*************************************************************************
* 函数名称:TIMER_TABLE* CreatTimer(
* uint32 dwTimeout,
* uint8 ucPeriodic,
* TMRCALLBACK pfTimerCallback,
* void *pArg)
* 功能说明:创建并启动软件定时器
* 输入参数:uint32 dwTimeout 0~0xFFFFFFFF 定时时间
uint8 ucPeriodic SINGLE 单次触发
PERIODIC 周期触发
TMRCALLBACK pfTimerCallback 定时结束时回调函数
void *pArg 回调函数参数
* 输出参数:无
* 返 回 值:操作失败 : NULL
操作成功 : 定时器模块指针
* 其它说明:创建完定时器后返回定时器结点的地址,改地址用于重启或删除该定时器
**************************************************************************/
TIMER_TABLE* CreatTimer(
uint32 dwTimeout,
uint8 ucPeriodic,
TMRCALLBACK pfTimerCallback,
void *pArg);
/*************************************************************************
* 函数名称:int KillTimer(TIMER_TABLE* ptNode)
* 功能说明:删除定时器结点
* 输入参数:TIMER_TABLE* ptNode 定时器结点地址
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
extern int KillTimer(TIMER_TABLE* ptNode);
/*************************************************************************
* 函数名称:int ResetTimer(TIMER_TABLE* ptNode)
* 功能说明:重启定时器结点
* 输入参数:TIMER_TABLE* ptNode 定时器结点地址
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
extern int ResetTimer(TIMER_TABLE* ptNode);
/*************************************************************************
* 函数名称:int ProcessTimer(void)
* 功能说明:更新定时器结点
* 输入参数:无
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
extern int ProcessTimer(void);
#ifdef __cplusplus
}
#endif
#endif
/* end of file */
/******************************************************************************
* 文件名称:SoftTimer.c
* 内容摘要:软件定时器模块
* 其他说明:首先运行TimersInit函数,需向该函数提供"1ms的系统时钟"和"最大系统ms数",
* 然后在各自的应用模块中调用CreatTimer创建定时器,该函数返回的地址为该定
* 时器的地址,可用与重启或删除定时器结点,请妥善保管。请在主循环中执行
* ProcessTimer函数以更新定时器时间。
* 当前版本:V1.00
* 作 者: zgj
* 完成日期:2018年2月20日
******************************************************************************/
#include "SoftTimer.h"
#include "stdio.h"
#include "string.h"
#include<stdlib.h>
static TIMER_TABLE* sg_ptTimeTableHead = NULL; /* 链表表头 */
static TMRSOURCE sg_pfSysClk = NULL; /* 系统1ms时钟函数 */
static unsigned long sg_dwTimeMaxValue = MAX_VALUE_32_BIT; /* 最大ms数 */
/*************************************************************************
* 函数名称:int TimersInit(TMRSOURCE pfTimer)
* 功能说明:初始化软件定时器模块
* 输入参数:TMRSOURCE pfTimer 系统1ms时钟函数
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
int TimersInit(TMRSOURCE pfTimer)
{
if (NULL == pfTimer)
{
return SW_ERROR; /* 检查注册函数是否为空指针 */
}
sg_ptTimeTableHead = (TIMER_TABLE*)malloc(sizeof(TIMER_TABLE)); /* 申请头结点 */
if (NULL == sg_ptTimeTableHead)
{
return SW_ERROR; /* 检查是否申请成功 */
}
/* 申请成功后进行初始化 */
sg_ptTimeTableHead->next = NULL; /* 下个结点地址置空 */
sg_pfSysClk = (TMRSOURCE)pfTimer; /* 注册系统1ms时钟函数 */
return SW_OK;
}
/*************************************************************************
* 函数名称:TIMER_TABLE* CreatTimer(
* uint32 dwTimeout,
* uint8 ucPeriodic,
* TMRCALLBACK pfTimerCallback,
* void *pArg)
* 功能说明:创建并启动软件定时器
* 输入参数:uint32 dwTimeout 0~0xFFFFFFFF 定时时间
uint8 ucPeriodic SINGLE 单次触发
PERIODIC 周期触发
TMRCALLBACK pfTimerCallback 定时结束时回调函数
void *pArg 回调函数参数
* 输出参数:无
* 返 回 值:操作失败 : NULL
操作成功 : 定时器模块指针
* 其它说明:创建完定时器后返回定时器结点的地址,改地址用于重启或删除该定时器
**************************************************************************/
TIMER_TABLE* CreatTimer(
uint32 dwTimeout,
uint8 ucPeriodic,
TMRCALLBACK pfTimerCallback,
void *pArg)
{
TIMER_TABLE* ptTimerNode;
TIMER_TABLE* ptFind;
if (NULL == sg_ptTimeTableHead)
{
return NULL; /* 检查链表头节点是否存在 */
}
/* 链表头结点已经存在 */
ptTimerNode = (TIMER_TABLE*)malloc(sizeof(TIMER_TABLE)); /* 申请定时器结点 */
if (NULL == ptTimerNode)
{
return NULL; /* 检查是否申请成功 */
}
/* 结点申请成功 */
ptTimerNode->next = NULL; /* 下个结点地址置空 */
ptTimerNode->data.periodic = ucPeriodic; /* 单次/周期触发 */
ptTimerNode->data.start = sg_pfSysClk(); /* 获取计时起始时间 */
ptTimerNode->data.now = ptTimerNode->data.start; /* 获取当前时间 */
ptTimerNode->data.elapse = 0; /* 已经过的时间 */
ptTimerNode->data.timeout = dwTimeout; /* 定时时间 */
ptTimerNode->data.pfTimerCallback = pfTimerCallback; /* 注册定时结束回调函数 */
ptTimerNode->data.pArg = pArg; /* 回调函数参数 */
/* 将新申请的定时器结点增加进入链表 */
ptFind = sg_ptTimeTableHead; /* 先找链表头结点 */
while(NULL != ptFind->next) /* 如果当前结点不是末尾结点*/
{
ptFind = ptFind->next; /* 将下一个结点的地址作为当前结点继续查找 */
}
/* 找到末尾结点 */
ptFind->next= ptTimerNode; /* 将新申请结点链接到末尾结点 */
return ptTimerNode; /* 操作成功,返回新申请结点地址(用于删除和重启计时) */
}
#if 1
/*************************************************************************
* 函数名称:int KillTimer(TIMER_TABLE* ptNode)
* 功能说明:删除定时器结点
* 输入参数:TIMER_TABLE* ptNode 定时器结点地址
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
int KillTimer(TIMER_TABLE* ptNode)
{
TIMER_TABLE* ptFind;
if (NULL == ptNode)
{
return SW_ERROR; /* 检查定时器结点是否为空 */
}
/* 定时器结点不为空 */
ptFind = sg_ptTimeTableHead; /* 先找到头结点 */
while (ptFind) /* 如果不是末尾结点 */
{
if (ptFind->next == ptNode) /* 检查下一结点是否为需删除结点 */
{
ptFind->next = ptNode->next; /* 重新链接上下结点 */
free(ptNode); /* 删除结点 */
return SW_OK; /* 操作成功,退出程序 */
}
ptFind = ptFind->next; /* 继续查找下一结点 */
}
return SW_ERROR; /* 未找到,操作失败 */
}
/*************************************************************************
* 函数名称:int ResetTimer(TIMER_TABLE* ptNode)
* 功能说明:重启定时器结点
* 输入参数:TIMER_TABLE* ptNode 定时器结点地址
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
int ResetTimer(TIMER_TABLE* ptNode)
{
if (NULL == ptNode)
{
return SW_ERROR; /* 检查定时器结点是否为空 */
}
ptNode->data.start = sg_pfSysClk(); /* 更新定时器起始时间 */
return SW_OK; /* 操作成功 */
}
/*************************************************************************
* 函数名称:int ProcessTimer(void)
* 功能说明:更新定时器结点
* 输入参数:无
* 输出参数:无
* 返 回 值:SW_ERROR: 操作失败
SW_OK 操作成功
* 其它说明:无
**************************************************************************/
int ProcessTimer(void)
{
TIMER_TABLE* ptFind;
TIMER_TABLE* ptNodeFree;
if (NULL == sg_ptTimeTableHead)
{
return SW_ERROR; /* 检查是否申请成功 */
}
ptFind = sg_ptTimeTableHead->next; /* 找到第一个有效结点 */
while(ptFind) /* 如果不是末尾结点 */
{
ptFind->data.now = sg_pfSysClk(); /* 更新时间 */
/* 计算此刻时间与起始时间的时间差 */
if(ptFind->data.now >= ptFind->data.start)
{
ptFind->data.elapse = ptFind->data.now - ptFind->data.start;
}
else
{
ptFind->data.elapse = sg_dwTimeMaxValue - ptFind->data.start + ptFind->data.now;
}
if(ptFind->data.elapse >= ptFind->data.timeout) /* 如果时差大于等于设定的计时时间 */
{
if(ptFind->data.pfTimerCallback) /* 且已经注册了合法的回调函数 */
{
ptFind->data.pfTimerCallback(ptFind->data.pArg); /* 执行回调函数 */
}
if(ptFind->data.periodic)
{
ResetTimer(ptFind); /* 如果是周期性触发,重启定时器 */
}
else
{ /* 如果是单次触发,删除定时器 */
ptNodeFree = ptFind;
ptFind = ptFind->next;
KillTimer(ptNodeFree);
continue;
}
}
ptFind = ptFind->next; /* 继续更新下一个定时器结点 */
}
return SW_OK; /* 操作成功 */
}
#endif
/* end of file */
软件定时器模块-STM32
最新推荐文章于 2024-05-17 09:04:04 发布