本帖最后由 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);
}
完!
|