VanZ7 发表于 2020-7-10 17:08:59

51单片机软定时器程序分享

之前自己的一个项目请教过坛友,如何对多个任务定时:
https://www.amobbs.com/thread-5735769-1-1.html

不少坛友都说软定时器可以解决。

这两天找到一个可以用的,分享给大家。

typedef enum tmrMode
{
        MODE_ONE_SHOT = 0, //单次模式
        MODE_PERIODIC,           //周期模式
} tmrMode;//定时器模式

typedef enum tmrState
{
        SOFT_TIMER_STOPPED = 0, //停止
        SOFT_TIMER_RUNNING,                //运行
        SOFT_TIMER_TIMEOUT,                //超时
        SOFT_TIMER_WAITING                //等待
} tmrState;//定时器状态。可通过函数获取这个状态。

typedef struct softTimer
{
        unsigned char state; //状态
        unsigned char mode;       //模式
        unsigned int period; //定时周期
        unsigned int count;       //定时计数用
        pFun callback;               //定时器回调函数
} softTimer;//定时器结构体。存储定时器任务内容及其他参数。


主要函数:
void softTimer_Creat(unsigned char id, tmrMode mode, unsigned int interval, pFun cb)
{
        softTimerList.mode = mode;
        softTimerList.period = interval;
        softTimerList.count = 0;
        softTimerList.callback = cb;
        softTimerList.state = SOFT_TIMER_STOPPED;
}
创建定时器,后面的变量分别是定时器编号、定时器模式(单次或循环)、定时器触发时间、定时器事件(一个指针,指向函数)

void softTimer_Start(unsigned int id)
{
        softTimerList.state = SOFT_TIMER_RUNNING;
}
//开启定时器
void softTimer_Stop(unsigned int id)
{
        softTimerList.state = SOFT_TIMER_STOPPED;
}
//停止定时器
void softTimer_Clr(unsigned int id)
{
        if (softTimerList.mode == MODE_ONE_SHOT)
        {
                softTimerList.state = SOFT_TIMER_STOPPED;
        }
        else
        {
                softTimerList.state = SOFT_TIMER_RUNNING;
        }
}
//清除定时器。如果定时器是单次触发模式,则定时器关闭;如果是循环模式,则重新开始计时。
unsigned char softTimer_GetState(unsigned int id)
{
        return softTimerList.state;
}
//获取定时器状态。

void softTimer_Update(void) //更新定时器状态,在硬件定时器中1ms调用一次
{
        unsigned char id;
        for (id = 0; id <= SOFT_TIMER_MAX; id++)
        {
                switch (softTimerList.state)
                {
                case SOFT_TIMER_STOPPED:
                        break;
                case SOFT_TIMER_RUNNING:
                        if (softTimerList.count < softTimerList.period)
                        {
                                softTimerList.count++;
                        }
                        else
                        {
                                softTimerList.count = 0;
                                softTimerList.state = SOFT_TIMER_TIMEOUT;
                                softTimerList.callback();
                        }
                        break;
                case SOFT_TIMER_TIMEOUT:
                        if (softTimerList.mode == MODE_ONE_SHOT)
                        {
                                softTimerList.state = SOFT_TIMER_STOPPED;
                        }
                        else
                        {
                                softTimerList.count++;
                                softTimerList.state = SOFT_TIMER_RUNNING;
                        }
                        break;
                default: //state error
                        break;
                }
        }
}//更新定时器状态,在中断中调用。

这个软定时器的缺点:不是很准确。如果定时时间长的话还好,误差基本上就抵消了,如果只是计时几个周期的话波形宽度会变,不适合做PWM,只适合秒级别的定时。
顺便原作者提供了一个protus的仿真,反正我是打不开。。。谁能打开谁玩玩吧。已经在“中颖”单片机上移植过了,很好用。


rei1984 发表于 2020-7-10 17:13:52

谢谢。 帮顶。。。。

yanbing080801 发表于 2020-7-10 22:50:34

8.9SP2仿真可以运行,{:victory:}回头看看怎样使用。

armok. 发表于 2020-7-12 02:35:48

打赏!

庆祝论坛“打赏”功能实施, 现在开始发技术主题,可以获得打赏
https://www.amobbs.com/thread-5735948-1-1.html

wgainn 发表于 2020-7-12 18:02:44

有问题,楼主 call_back()最好不能在中断里
页: [1]
查看完整版本: 51单片机软定时器程序分享