软件定时器(全部是C代码,可以在任何单片机上实现)

2019-08-19 18:22发布

本帖最后由 liuchang 于 2017-5-11 15:33 编辑

1>额,这个不是我原创,代码呢,也是我在网上东拼西凑的(在此感谢网上所有好心人...),如果有人觉得可以用,甚至好用,那是最好不过.如果使用过程中发现某些bug,还请各位神不惜赐教...
2>不用说,以某人目前的能力,不可能写出惊天的代码,本着难度可控的原则,本代码中没有使用类似ucos,lwip中的实现方式,直白点,能力不够(先想到,然后实现,能用即可,最后再想优化...)...

3>由于比较简单,没有搭demo版,附件只是提供.c和.h文件供各位参考.

4>软件定时器相对误差会比较大,ms级别,实时性要求如果很高,还是建议使用硬件定时器...

5>为什么需要软件定时器?
我的理解
1>硬件定时器不够用的时候
2>如果开启很多定时器并且使用中断,导致进入中断比较频繁,假设其中有个中断实时性很高,可能就因为处于其它中断中难以及时响应,就算可以中断嵌套,也会增加软件开销,并且中断管理相对复杂.
3>假设程序中仅仅需要开机3秒钟时"滴"一下,如果为这个3秒单独开个中断,似乎有点不值得.
4>假设程序中需要0.5s采集一次数据,再过0.2s将数据显示在屏上,此时使用软件定时器就比较合适,因为彼此之间有时间关联,类似于485"共模"抗干扰...

6>程序讲解
1>主要数据结构(注意,SOFT_TIMER_CALL_CYCLE =10,我在程序中定义扫描周期为10ms,这个随便弄个定时器都很容易实现吧,我就不贴出这个代码了)
[mw_shl_code=c,true]#define SOFT_TIMER_MAX_NUM      5
#define SOFT_TIMER_CALL_CYCLE   10
#define SOFT_TIMER_USE_OS       0

typedef void (*SOFT_TIMER_CB)(void *arg);

typedef enum
{
    SOFT_TIMER_NO_ERR,
    SOFT_TIMER_PARA_ERR,
}soft_timer_error_t;

typedef enum
{
    SOFT_TIMER_STOP = 0,
    SOFT_TIMER_START
}soft_timer_state_t;

typedef enum
{
    SOFT_TIMER_ONLY = 0,
    SOFT_TIMER_ALWAYS
}soft_timer_mode_t;

typedef struct
{
    uint8_t mode;
    uint8_t work;
    uint8_t state;
    uint32_t time;
    uint32_t save;
    SOFT_TIMER_CB soft_timer_cb;
    void * soft_timer_arg;
}soft_timer_t;[/mw_shl_code]
2>开启软件定时器
[mw_shl_code=c,true]soft_timer_error_t soft_timer_start(uint8_t timer, uint8_t mode, uint32_t time, SOFT_TIMER_CB soft_timer_cb, void * soft_timer_arg)
{
    if (timer >= SOFT_TIMER_MAX_NUM)
    {
        return SOFT_TIMER_PARA_ERR;
    }
   
#if SOFT_TIMER_USE_OS
    soft_timer_enter_critical();
#endif
   
    SoftTimer[timer].time = time/SOFT_TIMER_CALL_CYCLE;
    SoftTimer[timer].save = SoftTimer[timer].time;
    SoftTimer[timer].mode = mode;
    SoftTimer[timer].soft_timer_cb = soft_timer_cb;
    SoftTimer[timer].soft_timer_arg = soft_timer_arg;
    SoftTimer[timer].state = SOFT_TIMER_START;
   
#if SOFT_TIMER_USE_OS
    soft_timer_exit_critical();
#endif
   
     return SOFT_TIMER_NO_ERR;
}[/mw_shl_code]
3>关闭软件定时器
[mw_shl_code=c,true]soft_timer_error_t soft_timer_stop(uint8_t timer)
{
    if (timer >= SOFT_TIMER_MAX_NUM)
    {
        return SOFT_TIMER_PARA_ERR;
    }

#if SOFT_TIMER_USE_OS
    soft_timer_enter_critical();
#endif
   
     SoftTimer[timer].state = SOFT_TIMER_STOP;
   
#if SOFT_TIMER_USE_OS
    soft_timer_exit_critical();
#endif
   
    return SOFT_TIMER_NO_ERR;
}[/mw_shl_code]

4>这个需要在中断服务函数中实现


[mw_shl_code=c,true]void soft_timer_in_isr(void)
{
    uint8_t index;
   
#if SOFT_TIMER_USE_OS
    soft_timer_enter_critical();
#endif
   
    for (index = 0; index < SOFT_TIMER_MAX_NUM; index++)
    {
        if (SoftTimer[index].state)
        {
            if (SoftTimer[index].time)
            {
                SoftTimer[index].time--;
            }
            else if (SoftTimer[index].time == 0)
            {
                SoftTimer[index].work++;
                if (SoftTimer[index].mode == SOFT_TIMER_ALWAYS)
                {
                    SoftTimer[index].time = SoftTimer[index].save;
                }
                else
                {
                    SoftTimer[index].state = SOFT_TIMER_STOP;
                }
            }
        }
    }
   
#if SOFT_TIMER_USE_OS
    soft_timer_exit_critical();
#endif
}[/mw_shl_code]
6>这部分放在while(1)中运行
[mw_shl_code=c,true]void soft_timer_porcess(void)
{
    uint8_t index;
   
    for (index=0; index<SOFT_TIMER_MAX_NUM; index++)
    {
        if (SoftTimer[index].work)
        {
            SoftTimer[index].soft_timer_cb(SoftTimer[index].soft_timer_arg);
            SoftTimer[index].work--;
        }
    }
}[/mw_shl_code]
7>如下代码依赖具体的环境(例如我没上系统,直接关闭宏,SOFT_TIMER_USE_OS=0,不开启)
[mw_shl_code=c,true]void soft_timer_enter_critical(void)
{
}
void soft_timer_exit_critical(void)
{
}
#endif[/mw_shl_code]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。