yikuang 发表于 2015-11-15 19:12:57

我也发一个简单实用的软件定时器模块,支持延时模式和...

本帖最后由 yikuang 于 2015-11-15 19:16 编辑

尽管有人发过这样的帖子。。。

模块外部,用户只需提供一个硬件定时器作为软件定时器的最小时基和回调函数的实体即可。

sftmr.c
#include "bsp.h"
#include "sftmr.h"

/*! \brief initialize a soft timer
*! \param *ptSftmr pionter to a soft timer
*! \retval none
*! \note
*/
void sftmr_init(sftmr_t *ptSftmr)
{
    if (NULL == ptSftmr) {
      return ;
    }

    /*initialize all members of the object*/
    ptSftmr->Style = 0;
    ptSftmr->IsEnabled = SFTMR_DISABLE;
    ptSftmr->hwInterval = 0;
    ptSftmr->hwCounter = 0;
    ptSftmr->pfnCallBack = NULL;
}

/*! \brief the soft timer is used as delay mode with the interval time
*! \param *ptSftmr pionter to the specified soft timer
*! \param hwInterval interval time
    note the delay time depends on the time base of hardware timer
    delay time = hwInterval * time base
*! \retval none
*! \note the function should be called from anywhere except for interrupt
*/
void sftmr_delay(sftmr_t *ptSftmr, uint16_t hwInterval)
{
    if (NULL == ptSftmr) {
      return ;
    }

    /* work at delay mode */
    ptSftmr->Style = SFTMR_DELAY;
   
    ptSftmr->hwInterval = hwInterval;
    ptSftmr->hwCounter = hwInterval;
   
    /* no call back when delay */
    ptSftmr->pfnCallBack = NULL;
    ptSftmr->IsEnabled = SFTMR_ENABLE;

    /*delay until ptSftmr->hwCounter decrement to be 0*/
    while (ptSftmr->hwCounter > 0);

    ptSftmr->IsEnabled = SFTMR_DISABLE;
}


/*! \brief the soft timer is used as period mode with the interval time, and specifiy a callback.
*! \param *ptSftmr pionter to the specified soft timer
*! \param hwInterval interval time
    note the period time depends on the time base of hardware timer
    period time = hwInterval * time base
*! \param *pfnCallBack pionter to a callback which hanldes the user application when the
                        soft timer timed out
*! \retval none
*! \note the function should NOT be called from the loop
*/
void sftmr_period(sftmr_t *ptSftmr, uint16_t hwInterval, fnCallBack *pfnCallBack)
{
    if (NULL == ptSftmr || NULL == pfnCallBack) {
      return ;
    }

    ptSftmr->IsEnabled = SFTMR_DISABLE;
    ptSftmr->Style = SFTMR_PERIOD;
    ptSftmr->hwInterval = hwInterval;
    ptSftmr->hwCounter = hwInterval;
    ptSftmr->pfnCallBack = pfnCallBack;
    ptSftmr->IsEnabled = SFTMR_ENABLE;
}

/*! \brief the soft timer service routine
*! \param *ptSftmr pionter to the specified soft timer
*! \retval none
*! \note the function should be called from hardware timer interrupt service routine
*/
void sftmr_service(sftmr_t *ptSftmr)
{
    if (NULL == ptSftmr) {
      return ;
    }
   
    if (SFTMR_ENABLE == ptSftmr->IsEnabled) {
      if (ptSftmr->hwCounter > 0) {
            if (0 == (-- ptSftmr->hwCounter)) {
                if (SFTMR_PERIOD == ptSftmr->Style) {
                  /* reload the count value */
                  ptSftmr->hwCounter = ptSftmr->hwInterval;
                  /* call the user callback */
                  (*ptSftmr->pfnCallBack)();
                }
            }
      }
    }
}
















































































































sftmr.h
#ifndef _SOFT_TIMER_H_
#define _SOFT_TIMER_H_

#include "MacroAndConst.h"

#define SFTMR_PERIOD    0
#define SFTMR_DELAY   1

#define SFTMR_DISABLE   0
#define SFTMR_ENABLE    1

/* start up a sfot timer */
#define SFTMR_START(__SFTMR)   do { \
                                  __SFTMR->IsEnabled = SFTMR_ENABLE;\
                                  __SFTMR->hwCounter = __SFTMR->hwInterval; \
                               } while (false)

/* stop a sfot timer */
#define SFTMR_STOP(__SFTMR)    do { \
                                  __SFTMR->IsEnabled = SFTMR_DISABLE;\
                                  __SFTMR->hwCounter = 0; \
                               } while (false)                           

typedef void fnCallBack(void);

typedef struct {
    unsigned Style: 1;            /* sfot timer style */
    unsigned IsEnabled: 1;      /* sfot timer enable */
    uint16_t hwInterval;          /* sfot timer interval time */
    volatile uint16_t hwCounter;/* sfot timer counter */
    fnCallBack *pfnCallBack;      /* sfot timer callback function */
} sftmr_t;

void sftmr_init(sftmr_t *ptSftmr);
void sftmr_delay(sftmr_t *ptSftmr, uint16_t hwInterval);
void sftmr_period(sftmr_t *ptSftmr, uint16_t hwIterval, fnCallBack *pfnCallBack);
void sftmr_service(sftmr_t *ptSftmr);

#endif













































一个简单地例子:sftmr_t g_tSftmr1, g_tSftmr2;/* 定义软件定时器1,软件定时器2 */

void sftmr1_callback(void)
{
    /*添加用户代码,定时时间到后,会调用此回调函数*/
    indic_task(&g_tLed0);/*LED0 每秒闪一次*/
}

int main(void)
{
    ... ...
   
    /*初始化led1*/
    BSP_LED_Init(LED1);
    BSP_LED_Off(LED1);
   
    /*初始化led0*/
    indic_init(&g_tLed0, led0_on, led0_off);
   
    /*设置led0占空比*/
    LED_BLINKING(g_tLed0, 50, 100);
   
    /*初始化软件定时器1*/
    sftmr_init(&g_tSftmr1);
   
    /*初始化软件定时器2*/
    sftmr_init(&g_tSftmr2);
    /*设置软件定时器1的定时间隔,和回调函数*/
    sftmr_period(&g_tSftmr1, 10, sftmr1_callback);
   
    timer2_init(); /*初始化硬件定时器,时基为1ms*/
   
    while (1)
    {
      /*软件定时器2工作在延时模式*/
      /*led1 每两秒闪一次*/
      led1_on();
      sftmr_delay(&g_tSftmr2, 1000);
      led1_off();
      sftmr_delay(&g_tSftmr2, 1000);
      
      ... ...
    }
}

void Timer2_Handler(void)/*硬件定时器2中断服务*/
{
    sftmr_service(&g_tSftmr1);
    sftmr_service(&g_tSftmr2);
}

























































完!








yikuang 发表于 2015-11-15 19:18:19

有个单词拼写错了,可以无视。。。
sfot->soft

Gorgon_Meducer 发表于 2015-11-15 19:19:50

我想说,这个代码真好看!怎么做到的?

yikuang 发表于 2015-11-15 19:29:48

Gorgon_Meducer 发表于 2015-11-15 19:19
我想说,这个代码真好看!怎么做到的?

哈哈,这个问题问得好!
其实我也是无意中发现的。
1. 在帖子编辑框右上角的“纯文本框”左边的勾去掉;
2. 在notepad++上编辑好代码,然后全选,再右击:点击plugin commands->copy text with syntax highlighting。
3. 在帖子编辑框直接粘贴,完工!

估计有一大波人要感谢我了,哈哈哈!

wangjiati 发表于 2015-11-15 19:51:52

yikuang 发表于 2015-11-15 19:29
哈哈,这个问题问得好!
其实我也是无意中发现的。
1. 在帖子编辑框右上角的“纯文本框”左边的勾去掉;


好技能!

男小北 发表于 2015-11-15 20:12:21

这似乎是邵子扬写的一本书 里面的

yikuang 发表于 2015-11-15 20:28:46

男小北 发表于 2015-11-15 20:12
这似乎是邵子扬写的一本书 里面的

是参考他的

soos 发表于 2015-11-15 21:15:20

男小北 发表于 2015-11-15 20:12
这似乎是邵子扬写的一本书 里面的

什么书名?介绍一下

gujiamao_love 发表于 2015-11-15 21:33:02

陈工,讲解下

yikuang 发表于 2015-11-15 21:53:52

gujiamao_love 发表于 2015-11-15 21:33
陈工,讲解下

哪位陈工?

foxpro2005 发表于 2015-11-15 22:18:01

yikuang 发表于 2015-11-15 19:29
哈哈,这个问题问得好!
其实我也是无意中发现的。
1. 在帖子编辑框右上角的“纯文本框”左边的勾去掉;


强, 这个技能不错...

lyg407 发表于 2015-11-15 23:43:16

火钳刘明!

didadida 发表于 2015-11-16 13:50:34

while (ptSftmr->hwCounter > 0);差评{:lol:}{:lol:}

河图洛书 发表于 2015-11-16 14:09:08

这个延时,还是会阻塞程序吧,程序还要等待

huangqi412 发表于 2015-11-16 14:21:47

yikuang 发表于 2015-11-15 19:29
哈哈,这个问题问得好!
其实我也是无意中发现的。
1. 在帖子编辑框右上角的“纯文本框”左边的勾去掉;


收藏新技能

Shaopus 发表于 2015-11-16 15:05:21

yikuang 发表于 2015-11-15 19:29
哈哈,这个问题问得好!
其实我也是无意中发现的。
1. 在帖子编辑框右上角的“纯文本框”左边的勾去掉;


这个好!
感谢。

FireHe 发表于 2015-11-16 16:27:12

还是阻塞机制的吗?

yikuang 发表于 2015-11-16 16:34:51

FireHe 发表于 2015-11-16 16:27
还是阻塞机制的吗?

估计你们只看到阻塞模式的。。。 提供了两种模式,阻塞模式可以无视。

yikuang 发表于 2015-11-16 16:35:58

didadida 发表于 2015-11-16 13:50
while (ptSftmr->hwCounter > 0);差评

这是其中一种模式,觉得没意义可以无视

FireHe 发表于 2015-11-16 18:35:30

yikuang 发表于 2015-11-16 16:34
估计你们只看到阻塞模式的。。。 提供了两种模式,阻塞模式可以无视。

仔细看了一下,有 sftmr_period 这个函数

这个我觉得可以拓展一下,增加次数的控制。0是无限次,其他数字是对应调用次数。

yikuang 发表于 2015-11-16 18:52:42

FireHe 发表于 2015-11-16 18:35
仔细看了一下,有 sftmr_period 这个函数

这个我觉得可以拓展一下,增加次数的控制。0是无限次,其他数 ...

没必要这样吧。。。
也可以在回调函数计算次数,计数到了使用宏SFTMR_STOP就可以停止该定时器了,重新启动使用宏SFTMR_START就OK了
看个人喜好,爱怎么弄都可以{:lol:}

FireHe 发表于 2015-11-16 23:44:18

yikuang 发表于 2015-11-16 18:52
没必要这样吧。。。
也可以在回调函数计算次数,计数到了使用宏SFTMR_STOP就可以停止该定时器了,重新启 ...

也是,在回调函数里面计算也是一样的

lrzxc 发表于 2015-11-17 06:56:40

yikuang 发表于 2015-11-15 19:29
哈哈,这个问题问得好!
其实我也是无意中发现的。
1. 在帖子编辑框右上角的“纯文本框”左边的勾去掉;


这个经验不错,我是感谢人之一

creep 发表于 2015-11-17 07:27:02

代码不错,小技巧也很好,感谢分享

蓝蓝的恋 发表于 2015-11-17 08:15:24

好代码,下次试一下{:smile:}

renmin 发表于 2015-12-20 19:49:05

这个真的不错
受教了

spely 发表于 2015-12-20 22:04:13

代码不错,学习了~

polang200716 发表于 2015-12-22 22:22:05

最近在学习这个,谢谢

Yvan 发表于 2016-4-16 23:30:28

还没看,支持!!

shangyu60104 发表于 2016-9-22 14:44:49

很好,值得参考
页: [1]
查看完整版本: 我也发一个简单实用的软件定时器模块,支持延时模式和...