搜索
bottom↓
回复: 29
打印 上一主题 下一主题

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

  [复制链接]

出0入0汤圆

跳转到指定楼层
1
发表于 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);
}


























































完!









阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

2
 楼主| 发表于 2015-11-15 19:18:19 | 只看该作者
有个单词拼写错了,可以无视。。。
sfot->soft

出0入296汤圆

3
发表于 2015-11-15 19:19:50 | 只看该作者
我想说,这个代码真好看!怎么做到的?

出0入0汤圆

4
 楼主| 发表于 2015-11-15 19:29:48 | 只看该作者
Gorgon_Meducer 发表于 2015-11-15 19:19
我想说,这个代码真好看!怎么做到的?

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

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

出0入42汤圆

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

好技能!

出0入0汤圆

6
发表于 2015-11-15 20:12:21 | 只看该作者
这似乎是邵子扬写的一本书 里面的

出0入0汤圆

7
 楼主| 发表于 2015-11-15 20:28:46 | 只看该作者
男小北 发表于 2015-11-15 20:12
这似乎是邵子扬写的一本书 里面的

是参考他的

出0入0汤圆

8
发表于 2015-11-15 21:15:20 来自手机 | 只看该作者
男小北 发表于 2015-11-15 20:12
这似乎是邵子扬写的一本书 里面的

什么书名?介绍一下

出0入0汤圆

9
发表于 2015-11-15 21:33:02 | 只看该作者
陈工,讲解下

出0入0汤圆

10
 楼主| 发表于 2015-11-15 21:53:52 | 只看该作者

哪位陈工?  

出0入76汤圆

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

强, 这个技能不错...

出0入0汤圆

12
发表于 2015-11-15 23:43:16 | 只看该作者
火钳刘明!

出0入0汤圆

13
发表于 2015-11-16 13:50:34 | 只看该作者
while (ptSftmr->hwCounter > 0);差评

出0入0汤圆

14
发表于 2015-11-16 14:09:08 | 只看该作者
这个延时,还是会阻塞程序吧,程序还要等待

出0入0汤圆

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

收藏新技能

出0入0汤圆

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

这个好!
感谢。

出0入0汤圆

17
发表于 2015-11-16 16:27:12 | 只看该作者
还是阻塞机制的吗?

出0入0汤圆

18
 楼主| 发表于 2015-11-16 16:34:51 | 只看该作者
FireHe 发表于 2015-11-16 16:27
还是阻塞机制的吗?

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

出0入0汤圆

19
 楼主| 发表于 2015-11-16 16:35:58 | 只看该作者
didadida 发表于 2015-11-16 13:50
while (ptSftmr->hwCounter > 0);差评

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

出0入0汤圆

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

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

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

出0入0汤圆

21
 楼主| 发表于 2015-11-16 18:52:42 | 只看该作者
FireHe 发表于 2015-11-16 18:35
仔细看了一下,有 sftmr_period 这个函数

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

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

出0入0汤圆

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

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

出0入0汤圆

23
发表于 2015-11-17 06:56:40 来自手机 | 只看该作者
yikuang 发表于 2015-11-15 19:29
哈哈,这个问题问得好!
其实我也是无意中发现的。
1. 在帖子编辑框右上角的“纯文本框”左边的勾去掉;

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

出0入0汤圆

24
发表于 2015-11-17 07:27:02 来自手机 | 只看该作者
代码不错,小技巧也很好,感谢分享

出0入8汤圆

25
发表于 2015-11-17 08:15:24 | 只看该作者
好代码,下次试一下

出0入0汤圆

26
发表于 2015-12-20 19:49:05 | 只看该作者
这个真的不错
受教了

出0入0汤圆

27
发表于 2015-12-20 22:04:13 | 只看该作者
代码不错,学习了~

出0入0汤圆

28
发表于 2015-12-22 22:22:05 来自手机 | 只看该作者
最近在学习这个,谢谢

出0入0汤圆

29
发表于 2016-4-16 23:30:28 | 只看该作者
还没看,支持!!

出0入0汤圆

30
发表于 2016-9-22 14:44:49 | 只看该作者
很好,值得参考
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 03:13

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表