软件定时器模块-STM32

/******************************************************************************
* 文件名称: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 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱的远日点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值