打印
[程序源码]

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

[复制链接]
65909|106
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
misra|  楼主 | 2021-2-25 09:23 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 misra 于 2021-3-11 20:13 编辑

#申请原创#

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

需求1:让4个任务分别以1000ms、500ms、500ms、800ms周期性执行。怎么弄
直接给出需求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毫秒 周期性变化
                怎么弄?
直接给出应用代码:
/*-----------------------------------------------------*/
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[j])) {
                var[j]++;
            }
        }
    }
}

/*-----------------------------------------------------*/


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

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

使用特权

评论回复
评论
MMQ12 2021-5-25 21:15 回复TA
这个遇到任务中有延时的话就没法了吧,要不用状态机,状态机遇到大点的程序有太乱,代码量还增加不少。不好用哦 

相关帖子

沙发
misra|  楼主 | 2021-2-25 09:41 | 只看该作者
本帖最后由 misra 于 2021-3-13 19:42 编辑

1楼占个位
源码链接(21IC这个超链接似乎不好用,大家费点事,复制粘贴吧):
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[20];
u16 g_TaskBase[20] = {0};
const u16 TASK_IVL[20] = {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[i] >= TASK_IVL[i])
                        {
                                g_TaskVal[i]++;
                                g_TaskBase[i] += TASK_IVL[i];
                        }
                }
               
        }
}

使用特权

评论回复
地板
misra|  楼主 | 2021-2-25 10:02 | 只看该作者

一看就是很牛的了

再给你来个

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

使用特权

评论回复
5
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[i] >= TASK_IVL[i])
                        {
                                g_TaskVal[i]++;
                                g_TaskBase[i] += TASK_IVL[i];
                        }
                }
               
                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();
                }
        }
}

使用特权

评论回复
6
ayb_ice| | 2021-2-25 10:15 | 只看该作者
misra 发表于 2021-2-25 10:02
一看就是很牛的了

再给你来个

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

使用特权

评论回复
7
菜鸟同学| | 2021-2-25 10:23 | 只看该作者
就这,你十年功力,就玩这个。你就这个东西是很普通的软件定时器,到处都是源码,linux,和一些开源软件都有。
很多RTOS都有。
是定时器任务,不是什么框架。
看看下面这个才叫做framwork
http://www.state-machine.com/

使用特权

评论回复
评论
andy520520 2021-3-20 15:12 回复TA
我挺你。。。 
misra 2021-2-26 09:10 回复TA
@菜鸟同学 :况且这个内容并不水啊,还是有真正的干货的。可移植性超级好 可靠性 易用性都不错。尤其对初学者十分友好。像你说的那种linux那种实现 不是一般人能看的懂得吧 
misra 2021-2-26 09:06 回复TA
@菜鸟同学 :不搞点标题 怎么吸引眼球。你有更好的标题让帖子盖到100楼? 
菜鸟同学 2021-2-26 08:59 回复TA
@misra :我就不服你写的 这个标题,“真正的框架”,太狂了,必须打压下,哈哈,你有什么本事,全部拿出来。比划比划。 
misra 2021-2-26 08:56 回复TA
@菜鸟同学 :程序框架一般讲就是对某个功能或者部件的封装,让他成为一个标准件,达到拿来即用的目的。 我觉得把这个叫框架没问题。 这个肯定不是一无是处,还是有用的,尽管对你不一定有用。你看看后面网友的回复就行,还是不少人想知道其内部实现的。 另外提醒你: Talk is cheap. Show me your code 
菜鸟同学 2021-2-25 18:01 回复TA
@科技猎人 :哈哈,兄弟提醒的是,他标题 《真正的程序框架》 是不是有点过了,以为别人连软时钟这个东西都不知道。 
科技猎人 2021-2-25 16:39 回复TA
老兄,好不好的其实你心里清楚就好,没必要贬低别人。 
菜鸟同学 2021-2-25 13:22 回复TA
@misra :别激动,仔细看看我的发的这个东西,我的确不会写,你用windows开发,你自己要写windows吗,你用Linux开发,意思就是LInux源码都需要你自己写,自己实现? 真的很简单的一个软件定时器,普通不能再普通。你要是你能搞一个能像 本站农民讲习所和凤舞九天的MSOS那样的整套东西,你还可以秀一下,说成框架。 很多做MCU都悄悄的把这个软件定时器当成祖传。 
misra 2021-2-25 12:36 回复TA
Talk is cheap. Show me your code 
misra 2021-2-25 12:29 回复TA
是你写的算你牛!不是你写的 那和你有什么关系啊 
8
ayb_ice| | 2021-2-25 10:35 | 只看该作者
来个通用版的
typedef struct{
        u8 ucMax;
        u8 ucCur;
        bool bStart;
        bool bOut;
        u16 ausTick[8];        //最大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[i] = pTick[i];
        }
        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.ucCur])
                {
                        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[i] >= TASK_IVL[i])
                        {
                                g_TaskVal[i]++;
                                g_TaskBase[i] += TASK_IVL[i];
                        }
                }
               
                if (1)
                {
                        void LED_Ctrl(void);
                        LED_Ctrl();
                }
        }
}

使用特权

评论回复
9
gyh974| | 2021-2-25 11:10 | 只看该作者
支持百家争鸣,百花齐放

使用特权

评论回复
10
kissdb| | 2021-2-25 11:28 | 只看该作者
都来发下吧,

使用特权

评论回复
11
28936851| | 2021-2-25 11:31 | 只看该作者
非常简单的一个定时呀,一个计数器就可以分别产生

使用特权

评论回复
评论
misra 2021-2-25 12:31 回复TA
有句老话叫 请百度 “Talk is cheap. Show me your code.” 
12
lzm2008| | 2021-2-25 12:23 | 只看该作者
非常棒。

使用特权

评论回复
13
gyh02133| | 2021-2-25 12:26 | 只看该作者
20楼,早就有了

使用特权

评论回复
评论
zlf1208 2021-2-25 12:46 回复TA
哥,你在13楼 
14
zq_1943| | 2021-2-25 13:58 | 只看该作者
+1=14

使用特权

评论回复
15
gaoyang9992006| | 2021-2-25 15:35 | 只看该作者
用RTOS不就可以了,创建4个任务,各干各的。

使用特权

评论回复
16
zps136631| | 2021-2-25 17:07 | 只看该作者
进来看看。

使用特权

评论回复
17
lzsos369| | 2021-2-25 18:07 | 只看该作者
凑楼数

使用特权

评论回复
18
arima| | 2021-2-25 20:56 | 只看该作者
八仙过海,各显神通。。。。

使用特权

评论回复
19
lbc___| | 2021-2-25 21:13 | 只看该作者
看看楼主怎么实现的?

使用特权

评论回复
20
zhengy121| | 2021-2-25 21:40 | 只看该作者
这个可以学习下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名: 循序渐进,道自然而至...........

4

主题

276

帖子

2

粉丝