搜索
bottom↓
楼主: smset

再出个调度器,极小资源单片机值得一用

  [复制链接]

出0入0汤圆

发表于 2016-4-15 23:10:02 | 显示全部楼层
顶一下,这个还

出0入0汤圆

发表于 2016-4-27 16:29:45 | 显示全部楼层
坛友整理的小小调度器说明,写得非常好,可以作为小小调度器的基础教程使用。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-4-27 22:12:47 | 显示全部楼层
请问楼主哪里可以下载您的调度器的源码?

出0入0汤圆

发表于 2016-4-27 22:14:03 | 显示全部楼层
收起来学习

出0入0汤圆

发表于 2016-4-27 23:31:01 | 显示全部楼层
hotsauce1861 发表于 2016-4-27 22:12
请问楼主哪里可以下载您的调度器的源码?


本帖1153楼就是新版调度器的源码。
1213楼是坛友整理的资料,可当入门教程学习.

出0入0汤圆

发表于 2016-4-28 09:52:23 | 显示全部楼层
精妙源码,必须收藏!

出0入0汤圆

发表于 2016-4-28 12:28:46 | 显示全部楼层
收藏,楼主弄得的确不错~

出0入0汤圆

发表于 2016-4-29 15:49:01 | 显示全部楼层
看着不错,学习下

出0入0汤圆

发表于 2016-4-29 21:28:17 | 显示全部楼层
好东西 多谢lz分享!

出0入0汤圆

发表于 2016-4-30 23:43:11 | 显示全部楼层
很不错!                              

出0入0汤圆

发表于 2016-7-13 10:23:11 | 显示全部楼层
看啦N多次,谢谢楼主的无私供献!

出15入118汤圆

发表于 2016-7-21 07:47:00 来自手机 | 显示全部楼层
mark下,话说有推荐的版本吗?

出0入10汤圆

发表于 2016-7-21 10:24:50 | 显示全部楼层
下次尝试使用一下:)

出0入0汤圆

发表于 2016-7-21 17:10:41 | 显示全部楼层
现在,小小调度器已升级到 2.0版本了,解决了任务重入等问题。

  1. /****小小调度器开始**********************************************/
  2. #define TimeDef         unsigned short
  3. #define LineDef         unsigned char
  4. #define END             ((TimeDef)-1)
  5. #define LINE            ((__LINE__%(LineDef)-1)+1)  

  6. #define me  (*cp)
  7. #define TaskFun(TaskName)     TimeDef TaskName(C_##TaskName *cp) {switch(me.task.lc){default:
  8. #define Exit            do { me.task.lc=0; return END; }  while(0)
  9. #define Restart           do { me.task.lc=0; return 0; }  while(0)
  10. #define EndFun            } Exit; }

  11. #define WaitX(ticks)      do { me.task.lc=LINE; return (ticks); case LINE:;} while(0)
  12. #define WaitUntil(A)      do { while(!(A)) WaitX(0);} while(0)

  13. #define UpdateTimer(TaskVar)    do { if((TaskVar.task.timer!=0)&&(TaskVar.task.timer!=END)) TaskVar.task.timer--; }  while(0)
  14. #define RunTask(TaskName,TaskVar) do { if(TaskVar.task.timer==0) TaskVar.task.timer=TaskName(&(TaskVar)); }  while(0)

  15. #define CallSub(SubTaskName,SubTaskVar)    do { WaitX(0);SubTaskVar.task.timer=SubTaskName(&(SubTaskVar));      \
  16.                   if(SubTaskVar.task.timer!=END) return SubTaskVar.task.timer;} while(0)
  17.    
  18. /****************************************************************/
  19. #define Class(type)         typedef struct C_##type C_##type; struct C_##type
  20. Class(task)
  21. {
  22.   TimeDef timer;
  23.   LineDef lc;
  24. };
  25. void runtasks();
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入76汤圆

发表于 2016-7-21 19:14:18 | 显示全部楼层
不错,强烈支持, 看样子这次变化比较大

出0入0汤圆

发表于 2016-7-21 20:14:52 来自手机 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2016-7-22 08:40:20 | 显示全部楼层
这个真的要支持,先下载下来测试!

出0入0汤圆

发表于 2016-7-22 09:41:30 | 显示全部楼层
Nice,也研究一下

出0入0汤圆

发表于 2016-7-22 09:48:12 | 显示全部楼层
WaitX(100); 这个在mplab x + xc8 环境下还是不能编译通过,提示需要常量参数

出0入0汤圆

发表于 2016-7-22 15:36:16 | 显示全部楼层
好贴,希望有更多的人参与进来!

出0入4汤圆

发表于 2016-8-10 22:00:36 | 显示全部楼层
LZ能否新开个帖子,历经4年,2.0的变化有点大,写写注意事项,使用技巧。收获很多啊!

出0入4汤圆

发表于 2016-8-11 11:09:25 | 显示全部楼层
rundream 发表于 2016-7-21 17:10
现在,小小调度器已升级到 2.0版本了,解决了任务重入等问题。

楼主什么时候出完整版本的?你这个main里面的延时在stm32这种有systick的单片机里面怎么搞最优?

出0入0汤圆

发表于 2016-8-12 16:22:53 | 显示全部楼层
测试暂时没有问题,厉害呀楼主

出0入0汤圆

发表于 2016-8-12 17:29:52 | 显示全部楼层
不错,学习

出0入0汤圆

发表于 2016-8-12 23:31:12 | 显示全部楼层
靠,这是不死贴啊,四年升级成2.0了,楼主有没有更详细的说明

出0入0汤圆

发表于 2016-8-13 17:47:33 | 显示全部楼层
感谢分享,下载学习一下!

出0入0汤圆

发表于 2016-9-1 16:43:00 | 显示全部楼层
我想收藏本贴,没找着在哪收藏,好!!!!

出0入0汤圆

发表于 2016-9-28 19:31:10 | 显示全部楼层
本帖最后由 nos002 于 2016-9-29 00:30 编辑

像有人评说法律条文一样:说不服、绕湖涂。
switch语句的状态变量 _lc 根本不需要赋值行号,对_lc 任意赋值一个该变量类型的值(0、255除外)进行跳转 一样可以,如下所示:

  1. extern volatile uint8_t TaskTicks[MAXTASKS];

  2. #define SCH_BEGIN                                               \
  3.         static uint8_t  SCH_State = 0;                          \
  4.         switch( SCH_State ){                                    \
  5.              default:
  6.                                                         
  7. #define SCH_END                                                 \
  8.         ;};                                                       \
  9.         SCH_State = 0;                                          \
  10.         return 255;
  11. #define SCH_SUSPEND  return 255;

  12. #define SCH_DELAY( tickets )                                     \
  13.         do{                                                      \
  14.              if( SCH_State == 0 )                                \
  15.                 SCH_State = 1;                                   \
  16.              return (uint8_t)tickets;                            \
  17.         }while(0);                                               \
  18.         case 1:
复制代码
而楼主使用当前行号进行状态跳转的宏定义WaitX(ticks)必须写在同一行,为了可读性进行换行的话必须进行相应的修改,_lc 赋值要根据 case所在的行号进行加法运算,如下:

  1. #define SCH_DELAY( tickets )                                     \
  2.         do{                                                      \
  3.              _lc = (uint8_t)( ( __LINE__ + 5 ) & 0xff );         \
  4.              if( _lc == 0 )                                      \
  5.                  _lc = 1;                                        \
  6.              return (uint8_t)tickets;                            \
  7.         }while(0);                                               \
  8.         case (uint8_t)( ( __LINE__ & 0xff ) + ( __LINE__ & 0xff ) == 0 ) ):
复制代码


又或者如944楼 mute 的更直观简练的修改;再看了一下mute的SCH_DELAY宏,当前行号赋值和case所在行换行写还是错误的,要换行写只能如上进行加法运算。注:经实际运行还是mute是对的,上面的那个__LINE__ + 5无法运行
  1. #define SCH_MAX_TICK        0xFFFF
  2. #define SCH_MAX_TASK        16

  3. typedef volatile uint8_t   SCH_LC;
  4. typedef volatile uint16_t SCH_TICK;
  5. typedef volatile uint16_t SCH_SEM;
  6. typedef SCH_TICK SCH_TASK_RESULT;

  7. SCH_TICK SCH_TaskTicks[SCH_MAX_TASK];

  8. /******************************* 调度器 **********************************/
  9. #define SCH_LINE_NUM  ((__LINE__ + ((__LINE__ % 256) == 0)) % 256)


  10. #define SCH_TASK_BEGIN()                                                  \
  11.           static SCH_LC _sch_lc_ = 0;                                    \
  12.           switch (_sch_lc_)                                               \
  13.           {                                                               \
  14.             default:

  15. #define SCH_TASK_END()                                                    \
  16.             ;                                                             \
  17.           };                                                              \
  18.           _sch_lc_ = 0;                                                   \
  19.           return SCH_MAX_TICK

  20. #define SCH_DELAY(ticks)                                                  \
  21.           do                                                              \
  22.           {                                                               \
  23.             _sch_lc_ = SCH_LINE_NUM;                                      \
  24.             return ticks;                                               \
  25.           } while (0);                                                    \
  26.           case SCH_LINE_NUM:
复制代码




出0入0汤圆

发表于 2016-9-30 05:45:53 来自手机 | 显示全部楼层
又升级啦!

出0入0汤圆

发表于 2016-10-5 19:47:50 | 显示全部楼层
rundream 发表于 2016-7-21 17:10
现在,小小调度器已升级到 2.0版本了,解决了任务重入等问题。

小小调度器的作者已经很久没来了。被封了?

出0入0汤圆

发表于 2016-10-5 19:56:08 | 显示全部楼层
不错哇,这个贴还在继续!!!

出0入112汤圆

发表于 2016-10-6 12:02:06 | 显示全部楼层
没接触过调度器,下来学习一下!
厉害!谢谢分享!

出0入0汤圆

发表于 2016-10-21 13:24:42 | 显示全部楼层
学习一下。比直接大循环相比优越不少,而且纯C,不依赖处理器,占用资源也小,太巧妙了。

出5入10汤圆

发表于 2016-10-21 13:34:54 | 显示全部楼层
smset 发表于 2012-12-18 18:29
优化无止境!呵呵,330楼看似不能再优化了,但我再尝试做一次优化:

敬请评测该版本,看是否还能优化:在k ...

先收藏再说

出0入0汤圆

发表于 2016-10-25 22:56:40 | 显示全部楼层
又看一次!!

出0入0汤圆

发表于 2016-11-12 17:47:13 | 显示全部楼层
顶,备查,好东西

出0入0汤圆

发表于 2016-11-12 23:40:53 | 显示全部楼层
有没有信号量使用的example啊?

出0入0汤圆

发表于 2016-11-19 21:46:28 | 显示全部楼层
很好的帖子,要认真看看!!

出0入0汤圆

发表于 2016-12-17 21:48:20 | 显示全部楼层
学习一下!!!!

出0入0汤圆

发表于 2016-12-25 21:11:56 | 显示全部楼层
找了好久,先收藏起来,以后学习。

出0入0汤圆

发表于 2017-1-11 15:58:04 | 显示全部楼层
2017年是我的。

出0入0汤圆

发表于 2017-1-11 17:42:10 | 显示全部楼层
随然不懂,还是要顶

出0入0汤圆

发表于 2017-1-11 18:32:22 | 显示全部楼层
v2 产生的代码量太大了。不实用。

出30入0汤圆

发表于 2017-1-11 21:34:49 | 显示全部楼层
可以看看《基于时间触发嵌入式系统设计模式》

出0入0汤圆

发表于 2017-1-11 22:01:00 | 显示全部楼层
zan,不错的

出180入0汤圆

发表于 2017-1-12 09:46:52 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2017-1-14 18:27:16 | 显示全部楼层
  好思想 值得流传

出0入0汤圆

发表于 2017-5-31 21:33:52 | 显示全部楼层
非常值得学习

出0入0汤圆

发表于 2017-8-16 21:42:24 | 显示全部楼层
试用了一下楼主的调度器,用到按键的时候,不知道怎么去用了,楼主能出了实际的例子,包含常用的按键,串口通讯什么的。。。

出0入0汤圆

发表于 2017-9-1 14:23:37 | 显示全部楼层
这个调度器可以的 这么精简 拿过来用用

出0入0汤圆

发表于 2017-11-27 15:57:44 | 显示全部楼层
rundream 发表于 2016-4-27 23:31
本帖1153楼就是新版调度器的源码。
1213楼是坛友整理的资料,可当入门教程学习. ...

您好,请教你个问题:
我的项目中需要在任务中进入休眠,然后被外部引脚唤醒,唤醒后任务全部重新运行(像复位后的初始状态一样),我该怎么做?

我的想法:
1.如果我在任务中直接休眠,唤醒后继续恢复运行,我要怎样才能把任务重置为像复位后的状态一样开始?
2.如果我采用下面这种方式:

  1. while(1)
  2. {       
  3.         if(flag_cur==FLAG_SLEEP)
  4.         {
  5.                 //goto sleep and wait for wakup by Sensor/SetKey.
  6.                 Init4Sleep();                       
  7.                 flag_cur=sleep();                                //sleep() will return FLAG_XXX
  8.         }
  9. #ifdef        TinyOS
  10.         InitTasks();
  11.         InitSem(SEM_getChar);//init sem
  12.         T2_init();
  13.         T2_SetTime(123);                        //2ms--HeartBeat
  14. #endif

  15.         while(flag_cur)                                //run loop until FLAG_SLEEP
  16.         {
  17.                 CLRWDT();
  18.                 RunTaskA(task1,1);                // run once.
  19.                 RunTaskA(task2,2);                // run by flag_cur, if should sleep, flag_cur=0;
  20.         }
  21. }
复制代码


会不会有如下问题:
a. sleep()函数能不能使用return;
b. InitTasks();能不能重置任务。

比较迷惑,望赐教。

出0入0汤圆

发表于 2018-6-2 09:25:05 | 显示全部楼层
楼主,最近用了下这个调度器,发现一个问题:如果我在某个任务的子函数内需要挂起该任务的时候无法处理?

出0入0汤圆

发表于 2018-6-2 09:49:19 | 显示全部楼层
WaitX(100);
这个等待只能放在task任务函数中,如果task任务下调用了另外一个函数,这个函数里面想调用等待就不行了,除非阻塞住所有的任务用死等方式。

出1310入193汤圆

发表于 2018-6-2 10:04:43 | 显示全部楼层
调度器 精简

出0入0汤圆

发表于 2018-6-6 10:53:14 | 显示全部楼层
先收藏起来,以后学习

出0入0汤圆

发表于 2018-6-6 20:34:09 | 显示全部楼层
收藏先,谢谢分享

出0入0汤圆

发表于 2018-7-13 11:00:54 | 显示全部楼层
本帖1152楼就是新版调度器的源码。
1211楼是坛友整理的资料,可当入门教程学习.刚刚看了下楼层是这么个情况

出0入0汤圆

发表于 2018-7-13 11:20:44 | 显示全部楼层
真的是很好的资源

出0入0汤圆

发表于 2018-7-20 09:32:44 | 显示全部楼层
我移植到STM32去看看行不行

出0入0汤圆

发表于 2018-7-20 21:24:08 | 显示全部楼层
没看懂宏用法,还是自己太菜了

出0入0汤圆

发表于 2018-8-8 14:31:58 | 显示全部楼层
学习了  谢谢分享

出0入0汤圆

发表于 2018-12-19 19:46:25 | 显示全部楼层
谢谢分享,学习了

出0入0汤圆

发表于 2018-12-19 20:38:47 | 显示全部楼层
有原理图吗??

出0入0汤圆

发表于 2019-2-17 15:16:45 | 显示全部楼层
学无止境,技术推陈出新,佩服佩服

出0入0汤圆

发表于 2019-4-15 21:17:23 | 显示全部楼层
向楼主致敬!
前面的楼层太多,我也没依次细看,比如1223楼的代码似乎也不错。
按照本人的编程习惯,参考了一些其它的程序,稍作了一些修改,将定时器改为了16位;
本以为char改为int就行,没想到在51单片机上WaitX(500)的时候出了BUG:延时不准。
经过多次测试总算明白了,8位机在读写16位变量时,若被中断打断,且中断里对该变量有写操作,则会出问题。
解决办法一是在读写16位变量时关中断(类似OS_ENTER_CRITICAL()),二是增加标志位使在主循环操作变量时中断里不对其操作。
以下为核心代码:
  1. /*--------------------------------------------------
  2. <小小调度器.C>
  3. 利用switch语句实现的合作式调度器


  4. 参考1:https://www.cnblogs.com/songdechiu/p/5793717.html
  5. <<Protothread 机制>>

  6. 参考2:http://www.amobbs.com/thread-5508723-1-1.html   
  7. <<再出个调度器,极小资源单片机值得一用>>
  8. 作者:smset
  9. 参考3:https://www.amobbs.com/forum.php?mod=viewthread&tid=5702323&highlight=%E8%B0%83%E5%BA%A6%E5%99%A8
  10. <<小小调度器1.1重新整理版,8位16位32位可以选择定义>>
  11. 作者:xyb852

  12. LCW修改:timer为int型
  13. LINE的处理参考问星整理版
  14. (__LINE__%255)+1,使行号为:1~255 (避开0,因为0是第一个case标签)
  15. _SS改名为_BEGIN
  16. _EE改名为_END
  17. default改为case 0 (万一后面误写了case 0,可引发error)
  18. currdt类型改为static
  19. 16位timers会比原版占用更多的内存

  20. 注意事项:
  21. 1.任务函数不超过254行,否则可能引起 __LINE__%255+1 重复
  22. 2.任务内部的变量,如果要跨过等待或延时,需定义为静态变量.
  23. 3.任务中慎用switch,不要在新的switch中WaitX、WaitSem,否则可能引起case 混乱
  24. 4.任务函数内不要再用return。
  25. 5.运行任务的TaskID不要重复
  26. 6.由CallSub调用的任务,不能两个地方同时调用,主循环也不能再RunTask。
  27. 7.timer定义为16位时有个问题,读取timer时需关中断,否则可能在256附近读到0,
  28.   (8位机读取16位是分两次读取的,中间被中断打断并写入则会引起BUG)
  29.   也可另加循环调用WaitX实现长延时,这样就不需关中断了。
  30.   若不关中断,读两次连续为0也可以确定其为0;
  31.   写入timer时增加tmren标志,只有tmren置1后中断里才会进行减计数,这样就不会乱了。
  32. //--------------------------------------------------*/
  33. /****小小调度器开始**********************************************/
  34. //最大任务数
  35. #define MAXTASKS 3
  36. //最大等待时间,此时任务停止
  37. #define TICKET_MAX 0xFFFF
  38. //任务类型,也是定时器的数据类型
  39. #define TASK                         unsigned int
  40. #define TIMER                        unsigned int
  41. //记录标号,下次进入函数就往下进行
  42. #define LC_SET()                 _lc=(__LINE__%255)+1; case (__LINE__%255)+1:
  43. //初始化定时器
  44. #define InitTasks()         {unsigned char i; for(i=0;i<MAXTASKS;i++) timers[i]=0; }
  45. //任务开始
  46. #define _BEGIN                        static volatile unsigned char _lc=0; switch(_lc){case 0:
  47. //任务结束,不再进入
  48. #define _END                         } _lc=0; return TICKET_MAX;
  49. //延时
  50. #define WaitX(tickets)         do {_lc=(__LINE__%255)+1; return tickets ;} while(0); case (__LINE__%255)+1:
  51. //运行任务
  52. //#define RunTask(TaskName,TaskID)        do{ if (timers[TaskID]==0) timers[TaskID]=TaskName(); }while(0);
  53. /*
  54. //16位timer,读写时需关中断,避免读写过程中被修改
  55. #define RunTask(TaskName,TaskID)        do{EA=0;timert=timers[TaskID];EA=1;\
  56.                                                                         if (timert==0) {timert=TaskName();\
  57.                                                                         EA=0;timers[TaskID]=timert;EA=1;}}while(0);
  58. */
  59. //16位timer,两次读取都为0才认为是0,写入时要关使能位(或关中断)。
  60. #define RunTask(TaskName,TaskID)        do\
  61.                                                                         {\
  62.                                                                                 if((timers[TaskID]==0)&&(timers[TaskID]==0))\
  63.                                                                                 {\
  64.                                                                                         timert=TaskName();\
  65.                                                                                         tmren[TaskID]=0;\
  66.                                                                                         timers[TaskID]=timert;\
  67.                                                                                         tmren[TaskID]=1;\
  68.                                                                                 }\
  69.                                                                         }while(0);

  70. //continue使前面的任务优先保证执行
  71. //#define RunTaskA(TaskName,TaskID)        { if (timers[TaskID]==0) {timers[TaskID]=TaskName(); continue;} }
  72. #define RunTaskA(TaskName,TaskID)        {\
  73.                                                                                 if((timers[TaskID]==0)&&(timers[TaskID]==0))\
  74.                                                                                 {\
  75.                                                                                         timert=TaskName();\
  76.                                                                                         tmren[TaskID]=0;\
  77.                                                                                         timers[TaskID]=timert;\
  78.                                                                                         tmren[TaskID]=1;\
  79.                                                                                         continue;\
  80.                                                                                 }\                                                                       
  81.                                                                         }
  82. //调用任务函数(去掉了return 0)
  83. #define CallSub(SubTaskName)                 do{static TIMER currdt;LC_SET();currdt=SubTaskName();if(currdt!=TICKET_MAX) return currdt;} while(0);
  84. //#define CallSub(SubTaskName)                 do{static TIMER currdt; _lc=(__LINE__%255)+1; return 0;case (__LINE__%255)+1:currdt=SubTaskName();if(currdt!=TICKET_MAX) return currdt;} while(0);

  85. //定时中断里调用此函数用于计时
  86. //#define UpdateTimers()                                 {unsigned char i; for(i=0;i<MAXTASKS;i++){if((timers[i]!=0)&&(timers[i]!=TICKET_MAX)) timers[i]--;}}
  87. //tmren[i]非0才计数
  88. #define UpdateTimers()                                 {unsigned char i; for(i=0;i<MAXTASKS;i++){if((tmren[i]!=0)&&(timers[i]!=0)&&(timers[i]!=TICKET_MAX)) timers[i]--;}}

  89. //信号量类型
  90. #define SEM                                                 TIMER
  91. //初始化信号量
  92. #define InitSem(sem)                                 sem=0;
  93. //等待信号量(作了改动,return 0能更快响应,return 1 则可释放CPU一段时间)
  94. #define WaitSem(sem)                                 do{ sem=1; LC_SET(); if (sem>0) return 0;} while(0);
  95. //#define WaitSem(sem)                                 do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
  96. //等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
  97. #define WaitSemX(sem,tickets)                 do{ sem=tickets+1; LC_SET(); if(sem>1){ sem--;return 1;} } while(0);
  98. //#define WaitSemX(sem,tickets)                 do{ sem=tickets+1; WaitX(0); if(sem>1){ sem--;return 1;} } while(0);
  99. //发送信号量
  100. #define SendSem(sem)                                sem=0;
  101. //等待条件成立(return 0能更快响应,return 1 则可释放CPU一段时间)
  102. #define WaitCond(cond)                                 do {LC_SET();if(!(cond))return 0; }while(0);
  103. //--------------------------------------------------上面的可作为头文件,下面的不可重复定义
  104. //定义定时器数组
  105. volatile TIMER timers[MAXTASKS]={0};//注意初值要为0
  106. volatile char tmren[MAXTASKS]={0};//定时器使能
  107. volatile TIMER timert;//暂存
  108. //定义信号量
  109. SEM Sem1;
  110. char test1=0;
  111. /*****小小调度器结束*******************************************************/
  112. TASK task1(void)
  113. {
  114.         static char i=0;
  115.         char n;
  116.         _BEGIN
  117.         for(n=0;n<3;n++)
  118.                 U1Send(0xAA);

  119.         switch(n)
  120.         {
  121.                 case 1:U1Send(1);break;
  122.                 case 2:U1Send(2);break;
  123.                 case 3:U1Send(3);break;
  124.         }
  125.         U1Send(1);
  126.         LED_ON;
  127.         WaitX(500);
  128.         U1Send(2);
  129.         LED_OFF;
  130.         WaitX(1000);
  131.         U1Send(3);
  132.         LED_ON;
  133.         WaitX(500);
  134.         U1Send(4);
  135.         LED_OFF;
  136.         WaitX(500);
  137.         SendSem(Sem1);//发送信号量
  138.         for(i=0;i<10;i++)
  139.         {
  140.                 U1Send(5+i);       
  141.                 WaitX(1000);
  142.                 test1++;
  143.         }
  144.         _END
  145. }

  146. TASK task3(void)
  147. {
  148.         _BEGIN
  149.         WaitX(10);
  150.         U1Send(0x31);
  151.         _END
  152. }

  153. TASK task2(void)
  154. {
  155.         static char i=0x26;
  156.         _BEGIN

  157.         //WaitSem(Sem1);//等待信号量
  158.         WaitSemX(Sem1,1000);//只等1秒
  159.         U1Send(0x21);
  160.         WaitX(500);
  161.         U1Send(0x22);
  162.         WaitX(1000);
  163.         U1Send(0x23);
  164.         WaitCond(test1>8);//等待条件
  165.         U1Send(0x24);

  166.         CallSub(task3);//调用任务
  167.         U1Send(0x25);
  168.         while(1)
  169.         {               
  170.                 LED_XOR;
  171.                 U1Send(i++);
  172.                 WaitX(500);   
  173.         }

  174.         _END
  175. }

  176. /*
  177. //1KHz
  178. void timer0(void) interrupt 1
  179. {
  180.         UpdateTimers();
  181. }
  182. void main(void)
  183. {
  184.         init_devices();//初始化串口、定时器等
  185.         InitTasks();//可省
  186.         while(1)
  187.         {
  188.                 RunTask(task1,0);
  189.                 RunTask(task2,1);
  190.                 //PCON|=1;//睡眠
  191.         }
  192. }*/
复制代码

出0入0汤圆

发表于 2019-4-15 23:31:40 | 显示全部楼层
//任务结束,不再进入
#define _END                         ;}; _lc=0; return TICKET_MAX;

上述语句在KEIL C51中会有警告。为了消除警告,可改为:
#define _END                         ;};      //用于一直需要执行的任务
#define _END_CLOSE                        ;}; _lc=0; return TICKET_MAX;   //用于仅仅执行有限次的任务

出0入0汤圆

发表于 2019-7-18 17:15:50 | 显示全部楼层

原来几年前你就看到这个了

出0入0汤圆

发表于 2019-7-23 20:26:53 | 显示全部楼层
先收藏了,谢谢分享!

出0入0汤圆

发表于 2019-7-24 09:59:31 | 显示全部楼层
几年前的贴又翻出来,好好看看

出0入0汤圆

发表于 2019-10-4 16:46:30 | 显示全部楼层
多年老帖,思路真好,感谢楼主。

不过信号量这里793楼如果是异步发送信号量有很大的问题,

“读-改-写”没有任何临界保护,即便只是写int也会因为是非原子而出问题

出0入0汤圆

发表于 2019-12-9 19:39:02 | 显示全部楼层
不知有没有人把这种调度器用在实际项目里没有,还是仅仅大家只是玩一下。写几个玩具示例。

出0入0汤圆

发表于 2020-1-2 17:38:16 | 显示全部楼层
MARK  RTOS 调度器。。。。

出0入0汤圆

发表于 2020-4-2 13:43:40 | 显示全部楼层
收藏 mark

出0入0汤圆

发表于 2020-4-4 16:43:42 | 显示全部楼层
的确简单,小家电应该会很好用

出0入0汤圆

发表于 2020-9-1 11:58:49 | 显示全部楼层
用PICC V9.83移植到PIC单片机,源文件上的功能都实现了,但是不能运行SLEEP(),加上这句工作就不正常,不知道什么原因。

出0入0汤圆

发表于 2020-10-3 14:04:40 | 显示全部楼层
牛。。。。。。  学习下。。。。。。。。。。。。。。

出0入0汤圆

发表于 2020-11-2 17:22:27 | 显示全部楼层
收藏先,谢谢分享
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 19:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表