misra 发表于 2021-2-25 09:23

真正的单片机程序框架------->小巧的软件定时器....O(∩_∩)O

本帖最后由 misra 于 2021-3-11 20:13 编辑

#申请原创#
还在用各种标志位 全局变量搞定时器,换种更优雅的方式吧{:smile:}好了首先搞个需求引入 软件定时器的这个话题吧。

需求1:让4个任务分别以1000ms、500ms、500ms、800ms周期性执行。怎么弄?{:sweat:}直接给出需求1的代码:/*-----------------------------------------------------*/void test1(void)
{
    MLPeriod.init();
    while (1) {
      MLPeriod.run();
      if (MLPeriod.check(1000)) {
            //task1
      }
      if (MLPeriod.check(500)) {
            //task2
      }
      if (MLPeriod.check(500)) {
            //task3
      }
      if (MLPeriod.check(800)) {
            //task4
      }
    }
}
/*-----------------------------------------------------*/
需求2:让20个变量,分别以111,111,123,127,118,99,88,58,58,47,33,38,29,1111,2456,678,6789,457,451,20毫秒 周期性变化。            怎么弄?{:dizzy:}直接给出应用代码:/*-----------------------------------------------------*/ml_u32_t var[20] = {0}; //20个变量
ml_u32_t init_period[20] = {111, 111, 123, 127, 118, 99, 88, 58, 58, 47, 33, 38, 29, 1111, 2456, 678, 6789, 457, 451, 20}; //20个变量的周期值
void test (void)
{
    ml_u32_t j;
    MLPeriod.init();
    while (1) {
      MLPeriod.run();
      for (j = 0; j < 20; j++) {
            if (MLPeriod.check(init_period)) {
                var++;
            }
      }
    }
}
/*-----------------------------------------------------*/

代码是不是看起来很简单 没错!使用起来就是这么简单。

源码在1楼
有疑问或者建议请跟帖回复。

misra 发表于 2021-2-25 09:41

本帖最后由 misra 于 2021-3-13 19:42 编辑

1楼占个位
源码链接(21IC这个超链接似乎不好用,大家费点事,复制粘贴吧{:titter:}):
https://github.com/steven-lyan/microLite_timer/blob/main/src/microLite_timer.h
https://github.com/steven-lyan/microLite_timer/blob/main/src/microLite_timer.c




移植到51单片机的视频(电脑浏览器 单击鼠标全屏):


更多内容可关注微信公众号:microLite裸机系统


如果有空的话 ,可以去50楼逛一逛。



ayb_ice 发表于 2021-2-25 09:48

//1ms定时中断
u16 g_usTick;
void ISR_1ms(void)
{
        g_usTick++;
}

u16 GetCurTick(void)
{
        u16 ulTmp;
        __disable_int();
        ulTmp = g_usTick;
        __enable_int();
        return ulTmp;
}



u16 g_TaskVal;
u16 g_TaskBase = {0};
const u16 TASK_IVL = {111,456,123,127,118,99,88,77,58,47,33,38,29,1111,2456,678,6789,457,451,20};



void main(void)
{
        Init();
       
        while (1)
        {
                u8 i;
               
                for (i=0; i<20; i++)
                {
                        if (GetCurTick() - g_TaskBase >= TASK_IVL)
                        {
                                g_TaskVal++;
                                g_TaskBase += TASK_IVL;
                        }
                }
               
        }
}

misra 发表于 2021-2-25 10:02

ayb_ice 发表于 2021-2-25 09:48


一看就是很牛的了{:lol:}

再给你来个

一个灯亮3秒后 灭,111ms后亮,88ms后灭,999ms后亮

ayb_ice 发表于 2021-2-25 10:11

misra 发表于 2021-2-25 10:02
一看就是很牛的了

再给你来个


void main(void)
{
        Init();
       
        while (1)
        {
                u8 i;
               
                for (i=0; i<20; i++)
                {
                        if (GetCurTick() - g_TaskBase >= TASK_IVL)
                        {
                                g_TaskVal++;
                                g_TaskBase += TASK_IVL;
                        }
                }
               
                if (1)
                {
                        void LED_Ctrl(void);
                        LED_Ctrl();
                }
        }
}


//一个灯亮3秒后 灭,111ms后亮,88ms后灭,999ms后亮
void LED_Ctrl(void)
{
        static u8 s_ucLedStage = 0;
        static u16 s_ulBase;
        static bLed;
       
        switch(s_ucLedStage)
        {
                case 0:
                bLed = 1;
                if (GetCurTick() - s_ulBase >= 3000)
                {
                        bLed = 0;
                        s_ucLedStage++;
                        s_ulBase = GetCurTick();
                }
                break;
               
                case 1:
                if (GetCurTick() - s_ulBase >= 111)
                {
                        bLed = 1;
                        s_ucLedStage++;
                        s_ulBase = GetCurTick();
                }
                break;
               
                case 2:
                if (GetCurTick() - s_ulBase >= 88)
                {
                        bLed = 0;
                        s_ucLedStage++;
                        s_ulBase = GetCurTick();
                }
                break;
               
                case 3:
                if (GetCurTick() - s_ulBase >= 999)
                {
                        bLed = 1;
                        s_ucLedStage++;
                        s_ulBase = GetCurTick();
                }
                break;
               
                case 4:
                //完成
                break;
               
                if (bLed)
                {
                        LED_ON();
                }
                else
                {
                        LED_OFF();
                }
        }
}

ayb_ice 发表于 2021-2-25 10:15

misra 发表于 2021-2-25 10:02
一看就是很牛的了

再给你来个


针对这个问题,实际上我有专门的驱动来实现,但不是一两句代码能说的清楚的,分两步调用,第 一步
3000+111,完成后再调用88+999

菜鸟同学 发表于 2021-2-25 10:23

就这,你十年功力,就玩这个。你就这个东西是很普通的软件定时器,到处都是源码,linux,和一些开源软件都有。
很多RTOS都有。
是定时器任务,不是什么框架。
看看下面这个才叫做framwork
http://www.state-machine.com/

ayb_ice 发表于 2021-2-25 10:35

来个通用版的
typedef struct{
        u8 ucMax;
        u8 ucCur;
        bool bStart;
        bool bOut;
        u16 ausTick;        //最大8个状态
        u16 usBase;
}LED_Typedef;

LED_Typedef g_stLed;


void LED_Init(u16* pTick, bool bOut, u8 ucMax)
{
        u8 i;
       
        g_stLed.ucMax = ucMax;
        g_stLed.bOut = bOut;
        for (i=0; i<ucMax; i++)
        {
                g_stLed.ausTick = pTick;
        }
        g_stLed.ucCur = 0;
        g_stLed.usBase = GetCurTick();
        g_stLed.bStart = 1;
}

void LED_Ctrl(void)
{
        if (g_stLed.bStart)
        {
                if (GetCurTick() - g_stLed.usBase >= g_stLed.ausTick)
                {
                        g_stLed.bOut = !g_stLed.bOut;
                        g_stLed.usBase = GetCurTick();
                        g_stLed.ucCur++;
                        if (g_stLed.ucCur >= g_stLed.ucMax)
                        {
                                g_stLed.bStart = 0;
                        }
                }
               
                if (g_stLed.bOut)
                {
                        LED_ON();
                }
                else
                {
                        LED_OFF();
                }
        }
       
}


void main(void)
{
        Init();
       
        if (1)
        {
                //一个灯亮3秒后 灭,111ms后亮,88ms后灭,999ms后亮
                const u16 LED_TABLE[] = {3000,111,88,999};
                LED_Init(LED_TABLE, 1, 4);
        }
       
        while (1)
        {
                u8 i;
               
                for (i=0; i<20; i++)
                {
                        if (GetCurTick() - g_TaskBase >= TASK_IVL)
                        {
                                g_TaskVal++;
                                g_TaskBase += TASK_IVL;
                        }
                }
               
                if (1)
                {
                        void LED_Ctrl(void);
                        LED_Ctrl();
                }
        }
}

gyh974 发表于 2021-2-25 11:10

支持百家争鸣,百花齐放

kissdb 发表于 2021-2-25 11:28

都来发下吧,

28936851 发表于 2021-2-25 11:31

非常简单的一个定时呀,一个计数器就可以分别产生

lzm2008 发表于 2021-2-25 12:23

非常棒。

gyh02133 发表于 2021-2-25 12:26

20楼,早就有了

zq_1943 发表于 2021-2-25 13:58

+1=14

gaoyang9992006 发表于 2021-2-25 15:35

用RTOS不就可以了,创建4个任务,各干各的。

zps136631 发表于 2021-2-25 17:07

进来看看。

lzsos369 发表于 2021-2-25 18:07

凑楼数

arima 发表于 2021-2-25 20:56

八仙过海,各显神通。。。。

lbc___ 发表于 2021-2-25 21:13

看看楼主怎么实现的?

zhengy121 发表于 2021-2-25 21:40

这个可以学习下
页: [1] 2 3 4 5
查看完整版本: 真正的单片机程序框架------->小巧的软件定时器....O(∩_∩)O