搜索
bottom↓
楼主: smset

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

  [复制链接]

出0入0汤圆

发表于 2013-2-2 13:11:45 | 显示全部楼层
经典的调度器!!

出0入0汤圆

发表于 2013-2-21 20:27:10 | 显示全部楼层
实时性要求高的项目可能难以胜任了

出0入0汤圆

发表于 2013-2-22 21:52:35 | 显示全部楼层
好东西,学习了。。。

出0入0汤圆

发表于 2013-2-26 12:23:11 | 显示全部楼层
下来研究研究

出0入0汤圆

发表于 2013-2-27 09:21:46 | 显示全部楼层
楼主,新年过完了,可以继续讲课了。

出0入0汤圆

发表于 2013-3-4 22:59:18 | 显示全部楼层
任务调度,时间片轮询机制,不错,学习了

出0入0汤圆

发表于 2013-3-5 16:00:38 | 显示全部楼层
本帖最后由 shuxmpx123 于 2013-3-5 16:07 编辑

呵呵  楼主牛人啊,我正准备用protothread 的,看的一头雾水,正好看到你这个帖子,准备试用一下,不知楼主这个调度器跟protothread 相比如何,各有什么长短优缺啊··

出0入0汤圆

发表于 2013-3-6 11:28:00 | 显示全部楼层
请问 为什么我用STM8 的COSMIC编译器编译提示#error cpstm8 src\main.c:135(7) missing prototype   
RunTaskA(task1,1);//任务1具有比任务2高的运行权限                  
       RunTaskA(task2,2);//任务2具有低的运行权限
提示这2个函数无原型
用keil编译就没问题?                  

出0入0汤圆

发表于 2013-3-6 16:45:15 | 显示全部楼层
找到报错的原因了,

unsigned char task0() 改成
unsigned char task0(void)就可以了。。。。


出0入0汤圆

发表于 2013-3-6 17:29:07 | 显示全部楼层
本帖最后由 shuxmpx123 于 2013-3-6 17:30 编辑

谁能告诉我  
unsigned char  task2(void){
_SS
  while(1){
   WaitX(100);
   D3_BLINK();   
  }
_EE
}

unsigned char  task2(void){
   D3_BLINK();   
   return 100;
}
这样写有什么好处, 这个我没太看懂,貌似 task2里面的函数都只运行了一次? 不是像系统那样一种死循环运行?

出0入0汤圆

发表于 2013-3-6 20:56:25 | 显示全部楼层
很好啊~~正是需要

出0入0汤圆

发表于 2013-3-6 22:09:47 | 显示全部楼层
lihaolongli 发表于 2012-11-27 13:28
前边的宏定义看的不大明白


我也是看不懂宏定义,找了点资料。看后好多了

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2013-3-7 09:37:07 | 显示全部楼层
我觉得这个调度器不怎么样,
1、 任务多的时候  UpdateTimers();这里面的步骤也不少;
2、 RunTaskA(task1,1); 。。。。。 RunTaskA(taskn,1); 在主函数的while(1)里面,每个任务也还是要依次检测看时间有没有到;
3、_SS  _EE  WaitX  貌似没有必要,直接把任务函数放进去运行就可以了,如果是我没看懂这个地方的妙处,请大家指正;

下面的程序是我现在用的,感觉调度执行的步骤或许比楼主这个执行步骤更少:
          if (TIM4->SR1 & 0x01)
          {
                  TIM4->SR1 &= 0xFE;
                //TEST_K5_0_1();

                sys._500us++;
                if ((sys._500us&0x07) == 0)        // %8 == 0                4ms
                {
                        sys.task_4ms++;
                        if ((sys._500us&0x0F) == 0)        // %16 == 0                8ms
                        {
                                sys.task_8ms++;
                                if ((sys._500us&0x1F) == 0)        // %32 == 0                16ms
                                {
                                        sys.task_16ms++;
                                        if ((sys._500us&0x3F) == 0) // %64 == 0        // 32ms
                                        {
                                                sys.task_32ms++;
                                                sys._32ms++;
                                                if ((sys._32ms&0x03) == 0) // %4 == 0  128ms
                                                {
                                                        sys.task_128ms++;       
                                                        if ((sys._32ms&0x07) == 0)        // %8 == 0  256ms
                                                        {
                                                                sys.task_256ms++;
                                                                if (sys._32ms&0x0F)                // %16 == 0  512ms
                                                                {
                                                                        sys.task_512ms |= 0xFF;
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }

while(1)
        {
                if (sys.task_8ms > 1)
                {
                        //while(1);
                }
                if (sys.task_4ms)
                {
                        sys.task_4ms = 0;

                }
                if (sys.task_8ms)       
                {
                        Key_Scan();                                //扫描按键

                        sys.task_8ms = 0;
                }
                if (sys.task_16ms)       
                {

                        sys.task_16ms = 0;
                }

}

出0入0汤圆

发表于 2013-3-28 12:20:03 | 显示全部楼层
学习,任务调度

出0入0汤圆

发表于 2013-4-7 16:40:23 | 显示全部楼层
一口气看完整个帖子,获益良多!希望这个调度器越来越好!

出0入0汤圆

发表于 2013-4-8 08:24:34 | 显示全部楼层
由状态机到学习任务调度

出0入0汤圆

发表于 2013-4-8 12:56:17 | 显示全部楼层
smset 发表于 2012-12-21 11:57
综合这几天的讨论,先更新一版,仅供评测用:主要改动有: 1) 增加了RunTaskA宏,让前面的任务有优先执行 ...

我把这段程序手式展开看了几遍,还是有些疑问,请楼主及各位高手能解释下

1.信号量部分的宏定义了但后面都没有用到,可以直接注释掉吧?
  1. //#define SEM unsigned int
  2. //初始化信号量
  3. //#define InitSem(sem) sem=0;
  4. //等待信号量
  5. //#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
  6. //等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
  7. //#define WaitSemX(sem,tickets)  do { sem=tickets+1; WaitX(0); if(sem>1){ sem--;  return 1;} } while(0);
  8. //发送信号量
  9. //#define SendSem(sem)  do {sem=0;} while(0);
复制代码
2.任务函数的展开,如下
  1. unsigned char  task1()
  2. {
  3.     static unsigned char _lc;
  4.     switch(_lc)
  5.     {
  6.     default:while(1)
  7.         {
  8.         do {_lc=__LINE__+((__LINE__%256)==0); return 100 ;}
  9.          while(0);
  10.      case __LINE__+((__LINE__%256)==0):;
  11.          LED1=!LED1;
  12.          };
  13.     }; _lc=0; return 255;
  14. }
复制代码
while(1) 的作用范围跨过了case __LINE__+((__LINE__%256)==0),但while(1)的执行条件是default,而default与case __LINE__+((__LINE__%256)==0)应该是并列的啊,这段代码应该是怎样执行的?或者说,default与case之间应该是完整的代码吧,怎么就少了一个大括号呢?

出0入0汤圆

发表于 2013-4-9 11:35:10 | 显示全部楼层
renwocai 发表于 2013-4-8 12:56
我把这段程序手式展开看了几遍,还是有些疑问,请楼主及各位高手能解释下

1.信号量部分的宏定义了但后 ...

要结合RunTask宏展开分析!

出0入0汤圆

发表于 2013-4-9 15:52:31 | 显示全部楼层
bondxie3 发表于 2013-4-9 11:35
要结合RunTask宏展开分析!

谢谢回复,task1()不解决,RunTask就更没法看啦。

出0入0汤圆

发表于 2013-4-10 11:17:44 | 显示全部楼层
又看了几天,终于明白啦,原来while(1)的作用是执行完后一个case再强行拉回来记录一次行号。

现在还有一个问题,信号量是怎么使用的?能否给个简单的例程?

出0入0汤圆

发表于 2013-4-10 15:33:00 | 显示全部楼层
smset 发表于 2013-1-6 18:30
嗯,您说的很有道理。

可能本帖中有部分回帖认为: 小小调度器是 把时间片调度和protothread结合起来的 ...

“必须用的cpu(无法改换),仅仅只有512字节RAM, 8K字节ROM,而且我希望它干更多的事情。 ”

================================================================

闲逛的时候看到这么精彩的帖子,真实佩服各路高手。
不过我的看法是,
1,虽然小小调度器很精简,但它的代码只占整个系统的百分之一,再精简都会被其余的任务代码冗余掉。,
2,按照时间片的方式顺序调度各个任务,会打断任务的执行环境,编程时要实时考虑访问的内存是不是会被其它的任务修改,调度器很优美,但无疑会给开发者带来额外的困扰。
3,我还是倾向于使用状态机的方式,顺序处理各个任务,优先级高的任务多分配些状态,优先级低的少分配些。而且各个状态的执行函数都是在同一级,因此可以节省很多可贵的栈空间。

8K ROM,512Byte 也够用了。


出0入0汤圆

发表于 2013-4-10 17:48:09 | 显示全部楼层
我看了两天protothread,觉得还是使用状态机比较合适,明白了事,C语言就是追求简单易读,宏隐含太多东西!

出0入0汤圆

 楼主| 发表于 2013-4-10 18:09:09 | 显示全部楼层
himm007 发表于 2013-4-10 15:33
“必须用的cpu(无法改换),仅仅只有512字节RAM, 8K字节ROM,而且我希望它干更多的事情。 ”

========= ...

1,虽然小小调度器很精简,但它的代码只占整个系统的百分之一,再精简都会被其余的任务代码冗余掉。,

小小调度器除了本身小巧外,最大的用处是通过这个调度框架,写出的代码反而比状态机还省CPU资源.  所以前面说" 比裸奔还省资源 " ,就是这个意思.
2,按照时间片的方式顺序调度各个任务,会打断任务的执行环境,编程时要实时考虑访问的内存是不是会被其它的任务修改,调度器很优美,但无疑会给开发者带来额外的困扰。

你把小小调度器理解成抢占式多任务了, 但小小调度器不是抢占式多任务, 而是stackless的协作式调度, 不存在一个任务正在运行时,变量被其它的任务修改的可能性.也正是这样, 才会更加简化编程.
3,我还是倾向于使用状态机的方式,顺序处理各个任务,优先级高的任务多分配些状态,优先级低的少分配些。而且各个状态的执行函数都是在同一级,因此可以节省很多可贵的栈空间。

还是这个道理, 小小调度器是stackless的协作式调度器, 并不存在消耗更多的栈空间的问题.  所以函数依然是同一级的.

出0入0汤圆

 楼主| 发表于 2013-4-10 18:12:37 | 显示全部楼层
当你习惯于状态机时,你可能感觉不出状态机的问题. 然而当你习惯于调度器以后,你才会感觉出状态机的问题.

同样的道理:

当你习惯开手动挡汽车的时候, 你并不觉得多大的不方便.

但是当你习惯开自动档汽车以后,  你就再也不愿意开手动档汽车了.

出0入0汤圆

发表于 2013-4-10 18:35:32 | 显示全部楼层
强帖留名。。。。。。

出0入0汤圆

发表于 2013-4-11 14:14:49 | 显示全部楼层
帖子内容太多,你可以单独一个网页详细介绍这个么,个人网站或者新帖子什么的。
最好能把宏展开,这样好看懂些。

出0入0汤圆

发表于 2013-4-12 16:27:29 | 显示全部楼层
很好的思路,多谢了!

出0入0汤圆

发表于 2013-4-14 23:53:07 | 显示全部楼层
标记。。。。.

出0入0汤圆

发表于 2013-4-15 15:02:34 | 显示全部楼层
收藏了先。

出0入0汤圆

发表于 2013-4-16 12:16:58 | 显示全部楼层
smset 发表于 2013-4-10 18:12
当你习惯于状态机时,你可能感觉不出状态机的问题. 然而当你习惯于调度器以后,你才会感觉出状态机的问题.

...

   楼主,能不能放出一个综合性的工程。比如有串口,IIC,SPI,按键的模板。

出0入0汤圆

发表于 2013-4-16 22:47:47 | 显示全部楼层
有意义,高人!

出0入0汤圆

发表于 2013-4-26 21:15:54 | 显示全部楼层
在PIC mplab x  xc8 上编译,WaitX(50);出错,出错信息:constant expression required

出0入0汤圆

发表于 2013-5-6 21:48:52 | 显示全部楼层
smset思路很好!我在他的基础上改了一下,用于IAR c++ 编泽
有些没有完工!对共享变量加入临界保护!写的不好,不要扔砖头哦!
#ifndef WEEAOS_H
#define WEEAOS_H

#include "weea_cpu.h"

#define MAXTASKS   3u

#ifdef  WEEA_GLOBALS

volatile INT16U weea_timers[MAXTASKS] = {0};

#else

extern INT16U weea_timer[MAXTASKS];

#endif


#define  WEEA_BEGIN()                 static INT16U _lc; switch(_lc) { default:
#define  WEEA_END()                   } _lc = 0; return 0xffff;

#define  WaitX(ticks)                 do{_lc = __LINE__;return ticks;}while(0); case __LINE__:

#define  RunTask(TaskName,TaskID)     do{  if(weea_timers[TaskID] == 0) \
                                           {  \
                                             INT16U _trvalue = TaskName(); \
                                             OS_ENTER_CRITICAL(); \
                                             weea_timers[TaskID] = _trvalue; \
                                             OS_EXIT_CRITICAL(); \
                                           }  \
                                         }while(0);

#define RunTaskEx(TaskName,TaskID)      if(weea_timers[TaskID] == 0) \
                                        { \
                                           INT16U _trvalue = TaskName(); \
                                           OS_ENTER_CRITICAL(); \
                                           weea_timers[TaskID] = _trvalue; \
                                           OS_EXIT_CRITICAL(); \
                                           continue; \
                                         }

#define CallSub(SubTaskName)            do { WaitX(0); INT16U _curr_td = SubTaskName(); if(_curr_td != 0xffff) return _curr_td;} while(0);
#define UpdateTimers()                  { for(INT8U i=MAXTASKS; i>0 ;i--){if((weea_timers[i-1] != 0) && (weea_timers[i-1] != 0xffff)) weea_timers[i-1]--;}} //一定要在中断中调用

//weeaOS returen reslut value define   
#define   PT_R_MUT     0    //等待MUT信号量
#define   PT_R_SEM     0    //等待MUT信号量
#define   PT_R_TMO     255  //等待超时
#define   PT_R_OK      1    //等到一个对应结果,如等到一个MUT,或一个SEM,或其它

// MUT信号量支持
typedef  bool  Tmut;
#define  mut_create(A,B) \
             Tmut A = B
#define mut_create_extern(A) \
            extern Tmut A
#define  SendMut(A)       do{ (A) = true; }while(0);
#define  WaitMut(A)      do{ WaitX(0); if(!(A)) return 1; }while(0);
#define  WaitMutX(A,B,Err)  \
         do{ WaitX(0);\
             static u16 __t=(B);\
             if(!(A)){if(__t!=0xffff){if(__t==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__t;}return 1;}(Err) = PT_R_OK;_WEEA_##__LINE__:\
         }while(0);

// SEM计数型信号量支持
typedef  INT8U  Tsem;
#define  sem_create(A,B) \
        Tsem A = B
#define sem_create_extern(A) \
        extern Tsem A




// 消息支持




#endif
      

出0入0汤圆

发表于 2013-5-6 22:03:07 | 显示全部楼层
稍修改了下,增加了注释:
#ifndef WEEAOS_H
#define WEEAOS_H

#include "weea_cpu.h"

#define MAXTASKS   3u

#ifdef  WEEA_GLOBALS

volatile INT16U weea_timers[MAXTASKS] = {0};

#else

extern INT16U weea_timer[MAXTASKS];

#endif


#define  WEEA_BEGIN()                 static INT16U _lc; switch(_lc) { default:
#define  WEEA_END()                   } _lc = 0; return 0xffff;

#define  WaitX(ticks)                 do{_lc = __LINE__;return ticks;}while(0); case __LINE__:

#define  RunTask(TaskName,TaskID)     do{  if(weea_timers[TaskID] == 0) \
                                           {  \
                                             INT16U _trvalue = TaskName(); \
                                             OS_ENTER_CRITICAL(); \
                                             weea_timers[TaskID] = _trvalue; \
                                             OS_EXIT_CRITICAL(); \
                                           }  \
                                         }while(0);

#define RunTaskEx(TaskName,TaskID)      if(weea_timers[TaskID] == 0) \
                                        { \
                                           INT16U _trvalue = TaskName(); \
                                           OS_ENTER_CRITICAL(); \
                                           weea_timers[TaskID] = _trvalue; \
                                           OS_EXIT_CRITICAL(); \
                                           continue; \
                                         }

#define CallSub(SubTaskName)            do { WaitX(0); INT16U _curr_td = SubTaskName(); if(_curr_td != 0xffff) return _curr_td;} while(0);
#define UpdateTimers()                  { for(INT8U i=MAXTASKS; i>0 ;i--){if((weea_timers[i-1] != 0) && (weea_timers[i-1] != 0xffff)) weea_timers[i-1]--;}} //一定要在中断中调用

//weeaOS returen reslut value define   
#define   PT_R_MUT     0    //等待MUT信号量
#define   PT_R_SEM     0    //等待MUT信号量
#define   PT_R_TMO     255  //等待超时
#define   PT_R_OK      1    //等到一个对应结果,如等到一个MUT,或一个SEM,或其它

// MUT互斥型信号支持
typedef  bool  Tmut;
#define  mut_create(A,B) \
             Tmut A = B
#define mut_create_extern(A) \
            extern Tmut A
#define  SendMut(A)       do{ (A) = true; }while(0);
#define  WaitMut(A)      do{ WaitX(0); if(!(A)) return 1; }while(0);

// A: mut型信号量,bool型
// B: 超时值,IN16U型
// Err: 返回等待结果,要求Err在调用前为0(PT_R_MUT或PT_R_SEM).
//      PT_R_MUT或PT_R_SEM: 信号量正等待中
//      PT_R_OK  : 等到一个信号
//      PT_R_TMO : 等到超时
#define  WaitMutX(A,B,Err)  \
         do{ WaitX(0);\
             static u16 __t=(B);\
             if(!(A)){if(__t!=0xffff){if(__t==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__t;}return 1;}(Err) = PT_R_OK;_WEEA_##__LINE__:\
         }while(0);

// SEM计数型信号量支持
typedef  INT8U  Tsem;
#define  sem_create(A,B) \
        Tsem A = B
#define sem_create_extern(A) \
        extern Tsem A




// 消息支持




#endif
      

出0入0汤圆

发表于 2013-5-6 22:16:31 | 显示全部楼层
用了n多RTOS,protothread确实叫人惊叹!如果测试没问题,可以支持消息、邮箱,以及类似keil RTX中的event事件!

出0入0汤圆

发表于 2013-5-6 22:53:32 | 显示全部楼层
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H

#include "weea_cpu.h"

#define MAXTASKS   3u

#ifdef  WEEA_GLOBALS

volatile INT16U weea_timers[MAXTASKS] = {0};

#else

extern INT16U weea_timer[MAXTASKS];

#endif


#define  WEEA_BEGIN()                 static INT16U _lc; switch(_lc) { default:
#define  WEEA_END()                   } _lc = 0; return 0xffff;

#define  WaitX(ticks)                 do{_lc = __LINE__;return ticks;}while(0); case __LINE__:

#define  RunTask(TaskName,TaskID)     do{  if(weea_timers[TaskID] == 0) \
                                           {  \
                                             INT16U _trvalue = TaskName(); \
                                             OS_ENTER_CRITICAL(); \
                                             weea_timers[TaskID] = _trvalue; \
                                             OS_EXIT_CRITICAL(); \
                                           }  \
                                         }while(0);

#define RunTaskEx(TaskName,TaskID)      if(weea_timers[TaskID] == 0) \
                                        { \
                                           INT16U _trvalue = TaskName(); \
                                           OS_ENTER_CRITICAL(); \
                                           weea_timers[TaskID] = _trvalue; \
                                           OS_EXIT_CRITICAL(); \
                                           continue; \
                                         }

#define CallSub(SubTaskName)            do { WaitX(0); INT16U _curr_td = SubTaskName(); if(_curr_td != 0xffff) return _curr_td;} while(0);
#define UpdateTimers()                  { for(INT8U i=MAXTASKS; i>0 ;i--){if((weea_timers[i-1] != 0) && (weea_timers[i-1] != 0xffff)) weea_timers[i-1]--;}} //一定要在中断中调用

//weeaOS return reslut value define   
#define   PT_R_MUT     0    //等待MUT信号量
#define   PT_R_SEM     0    //等待MUT信号量
#define   PT_R_TMO     255  //等待超时
#define   PT_R_OK      1    //等到一个对应结果,如等到一个MUT,或一个SEM,或其它

// MUT互斥型信号支持
typedef  bool  Tmut;
#define  mut_create(A,B) \
             Tmut A = B
#define mut_create_extern(A) \
            extern Tmut A
#define  SendMut(A)       do{ (A) = true; }while(0);
#define  WaitMut(A)      do{ WaitX(0); if(!(A)) return 1; }while(0);

// A: mut型信号,bool型
// B: 超时值,IN16U型
// Err: 返回等待结果,要求Err在调用前为0(PT_R_MUT或PT_R_SEM).
//      PT_R_MUT或PT_R_SEM: 信号量正等待中
//      PT_R_OK  : 等到一个信号
//      PT_R_TMO : 等到超时
#define  WaitMutX(A,B,Err)  \
         do{ WaitX(0);\
             static u16 __t=(B);\
             if(!(A)){if(__t!=0xffff){if(__t==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__t;}return 1;}(Err) = PT_R_OK;OS_ENTER_CRITICAL();(A)=false;OS_EXIT_CRITICAL();_WEEA_##__LINE__:\
         }while(0);

// SEM计数型信号支持
typedef  INT8U  Tsem;
#define  sem_create(A,B) \
        Tsem A = B
#define sem_create_extern(A) \
        extern Tsem A

#define SendSem(A)           do( (A)++; )while(0);
#define WaitSem(A)           do{ WaitX(0); if((A) == 0){return 1;} (A)--; }while(0);
#define WaitSemX(A,B,Err) \
do{\
   WaitX(0);static u16 __tt=(B);if((A)==0){if(__tt!=0xffff){if(__tt==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__tt;}return 1;}(Err)=PT_R_OK;OS_ENTER_CRITICAL();--(A);OS_EXIT_CRITICAL();_WEEA_##__LINE__:\
}while(0);

// 消息、邮箱支持
typedef  INT8U  Tmsg;
#define  msg_create(A,B) \
        Tmsg* A = B
#define msg_create_extern(A) \
        extern Tmsg* A
#define SendMsg(A)           
#define WaitMsg(A)           
#define WaitMsgX(A,B,Err) \



#endif

      

出0入0汤圆

发表于 2013-5-11 17:50:10 | 显示全部楼层
这个已用了好几个案子的开发了,它对C编译器适应性很强!

出0入0汤圆

 楼主| 发表于 2013-5-14 17:03:22 | 显示全部楼层
jangyouhua 发表于 2013-5-6 22:53
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H

修改得好,期待能进一步完善和优化。

出0入76汤圆

发表于 2013-5-15 00:23:02 | 显示全部楼层
本帖最后由 foxpro2005 于 2013-5-15 00:30 编辑
jangyouhua 发表于 2013-5-6 22:53
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H


互斥信号------ 这一部分好像有点问题....
WaitMut(A)      do{ WaitX(0); if(!(A)) return 1; (A)=false; }while(0);

出0入0汤圆

发表于 2013-5-22 10:24:00 | 显示全部楼层
小 调度器 mark一下

出0入0汤圆

发表于 2013-5-24 14:39:43 | 显示全部楼层
eddia2012 发表于 2013-5-11 17:50
这个已用了好几个案子的开发了,它对C编译器适应性很强!

我现在在用你的代码,Task_event_wait(D_wait_ever);    #define D_wait_ever     ((u8)-1)  这个宏是什么作用。

出0入0汤圆

发表于 2013-5-24 14:50:54 | 显示全部楼层
eddia2012 发表于 2013-5-11 17:50
这个已用了好几个案子的开发了,它对C编译器适应性很强!

Task2_display() 这个函数没看懂,        if(task_Wait_flag)  什么意思啊。
                        {
                                                   Task_subCall(subtask);
                        }

出0入0汤圆

发表于 2013-5-24 15:45:28 | 显示全部楼层
eddia2012 发表于 2012-12-16 22:34
希望加入事件触发优化。

你的代码加了吧。

出0入0汤圆

发表于 2013-6-12 08:44:15 | 显示全部楼层
不错

出0入0汤圆

发表于 2013-6-25 16:48:19 | 显示全部楼层
protothread

出0入0汤圆

发表于 2013-6-26 10:35:24 | 显示全部楼层
研究了一会,搞懂了。
真的很巧妙,赞一个。
看不懂的童鞋可以从楼主位那段代码开始,关键是task2,手动将宏展开,你将看到一种switch的变态用法,然后原理一目了然。__LINE__是语句所在的行号。
实际上在函数遇到延时返回前做了两件事:设置延时时间,设置状态变量lc,使得第二次进入函数时得到正确的跳转。

出0入0汤圆

发表于 2013-7-10 16:40:32 | 显示全部楼层
jangyouhua 发表于 2013-5-6 22:53
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H

能提供  weea_cpu.h 的代码吗?

出0入0汤圆

发表于 2013-7-31 20:55:52 | 显示全部楼层
支持。。谢谢分享哈..调度器博大精深哈~~

出0入0汤圆

 楼主| 发表于 2013-7-31 22:59:23 | 显示全部楼层


  1. #include <stc89c51.h>
  2. /****小小调度器开始**********************************************/
  3. #define MAXTASKS 3
  4. volatile unsigned char timers[MAXTASKS];
  5. #define _SS static unsigned char _lc; switch(_lc){default:
  6. #define _EE ;}; _lc=0; return 255;
  7. #define WaitX(tickets)  do {_lc=__LINE__; return tickets ;} while(0); case __LINE__:

  8. #define RunTask(TaskName,TaskID) do { if (timers[TaskID]==0) timers[TaskID]=TaskName(); }  while(0);
  9. #define RunTaskA(TaskName,TaskID) { if (timers[TaskID]==0) {timers[TaskID]=TaskName(); continue;} }   //前面的任务优先保证执行

  10. #define CallSub(SubTaskName) do {unsigned char currdt; _lc=__LINE__; return 0; case __LINE__:  currdt=SubTaskName(); if(currdt!=255) return currdt;} while(0);
  11. #define UpdateTimers() {unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers[i-1]!=0)&&(timers[i-1]!=255)) timers[i-1]--;}}

  12. #define SEM unsigned int
  13. //初始化信号量
  14. #define InitSem(sem) sem=0;
  15. //等待信号量
  16. #define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
  17. //等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
  18. #define WaitSemX(sem,tickets)  do { sem=tickets+1; WaitX(0); if(sem>1){ sem--;  return 1;} } while(0);
  19. //发送信号量
  20. #define SendSem(sem)  do {sem=0;} while(0);

  21. /*****小小调度器结束*******************************************************/


  22. sbit LED1 = P2^1;
  23. sbit LED2 = P2^2;

  24. sbit LED0 = P2^5;

  25. unsigned char task0(){
  26. _SS
  27.   while(1){
  28.    WaitX(50);
  29.    LED0=!LED0;   
  30.   }
  31. _EE
  32. }

  33. unsigned char  task1(){
  34. _SS
  35.   while(1){
  36.    WaitX(100);
  37.    LED1=!LED1;   
  38.   }
  39. _EE
  40. }

  41. unsigned char  task2(){
  42. _SS
  43.   while(1){
  44.    WaitX(100);
  45.    LED2=!LED2;   
  46.   }
  47. _EE
  48. }

  49. void InitT0()
  50. {
  51.         TMOD = 0x21;
  52.         IE |= 0x82;  // 12t
  53.         TL0=0Xff;
  54.         TH0=0XDB;
  55.         TR0 = 1;
  56. }

  57. void INTT0(void) interrupt 1 using 1
  58. {
  59.     TL0=0Xff;    //10ms 重装
  60.     TH0=0XDB;//b7;   

  61.     UpdateTimers();

  62.     RunTask(task0,0);//任务0具有精确按时获得执行的权限,建议:task0每次执行消耗时间<0.5个 ticket
  63. }




  64. void main()
  65. {
  66.         InitT0();
  67.         while(1){
  68.            //RunTask(task0,0);
  69.            RunTaskA(task1,1);//任务1具有比任务2高的运行权限                  
  70.            RunTaskA(task2,2);//任务2具有低的运行权限                  
  71.       }
  72. }
复制代码

出0入0汤圆

发表于 2013-8-1 17:20:57 | 显示全部楼层
Mark,学习

出0入0汤圆

发表于 2013-8-3 01:08:05 | 显示全部楼层
656楼的代码08行
#define _EE ;}; _lc=0; return 255;
后面的_lc=0; return 255;
程序不会运行这2句,不知道有什么作用?

出0入0汤圆

发表于 2013-8-14 09:05:06 | 显示全部楼层
不是跟时间触发嵌入式系统那本书里的一样么?

出0入0汤圆

 楼主| 发表于 2013-8-14 09:57:08 | 显示全部楼层
rossih 发表于 2013-8-14 09:05
不是跟时间触发嵌入式系统那本书里的一样么?

根本不一样,没有可比性。

出0入0汤圆

发表于 2013-8-16 11:03:20 | 显示全部楼层
smset 发表于 2013-8-14 09:57
根本不一样,没有可比性。

如果程序的行数超过255行,程序可以正常运行吗 ?

出0入0汤圆

 楼主| 发表于 2013-8-16 13:21:32 | 显示全部楼层
holts2 发表于 2013-8-16 11:03
如果程序的行数超过255行,程序可以正常运行吗 ?

可以正常运行的。

出0入0汤圆

发表于 2013-8-16 13:30:07 | 显示全部楼层
smset 发表于 2013-8-16 13:21
可以正常运行的。

我在stm8s103使用库,用到, 编绎正常,但程序不能正常运行,不知从何查起


  1.   
  2. #include "ptask.h"
  3. #include "stm8s.h"

  4. #define LED_GPIO_PORT  (GPIOA)
  5. #define LED_GPIO_PINS  (GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)
  6. #define SW_4  GPIO_PIN_1
  7. #define SW_5  GPIO_PIN_2
  8. #define LED_RUN_OR_WAIT   GPIO_PIN_3

  9. #define LED_GPIO_PORT2 (GPIOC)
  10. #define LED_GPIO_PINS2 (GPIO_PIN_5 | GPIO_PIN_6)  
  11. #define LED_WAIT   GPIO_PIN_5
  12. #define LED_RUN3   GPIO_PIN_6

  13. #define LED_GPIO_PORT3 (GPIOD)
  14. #define LED_GPIO_PINS3 (GPIO_PIN_6)
  15. #define LED_RUN    GPIO_PIN_6

  16. #define KEY_GPIO_PORT  (GPIOD)
  17. #define KEY_GPIO_PINS  (GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 )
  18. #define KEY_POWER   GPIO_PIN_1   
  19. #define KEY_REDUCE   GPIO_PIN_2
  20. #define KEY_PLUS  GPIO_PIN_3

  21. #define KEY_MODE_PINS (GPIO_PIN_4)
  22. #define KEY_MODE    GPIO_PIN_4
  23. #define KEY_TRIGGER_PINS (GPIO_PIN_5)
  24. #define KEY_TRIGGER  GPIO_PIN_5

  25. #define KEY_GPIO_PORT2  (GPIOC)
  26. #define KEY_SW_PINS (GPIO_PIN_7)
  27. #define KEY_SW    GPIO_PIN_7

  28. #define MilliSec        1
  29. #define Sec             1000

  30. #define STEP            5   //约5%
  31. #define MAX             70  //100%
  32. #define MIN             15  //约21%

  33. #define OFF             0
  34. #define ON              1
  35. #define RUN             2
  36. #define WAIT            3

  37. #define TIM4_PERIOD     124   //1ms定时


  38. void GPIO_Configuration(void);
  39. void TIM4_Config(void);
  40. void TimingDelay_Decrement(void);
  41. void PWM1_Init(void);
  42. void SetTIM1_PWM_DutyCycle(uint16_t TIM1_Pulse);

  43. unsigned char Blink(void);
  44. unsigned char SwRead(void);

  45. void KeyRead(void);
  46. unsigned char Key_thread(void);
  47. void LightReduce(void);
  48. void LightPlus(void);
  49. void PowerEvent(void);
  50. void SwEvent(void);

  51. void Write_Byte (unsigned int address,unsigned char Data);

  52. unsigned char task0(void);
  53. unsigned char task1(void);

  54. /* Private functions -------------------------------------------*/
  55. /* Global variables --------------------------------------------*/
  56. volatile unsigned char timers[MAXTASKS]={0};

  57. unsigned char Trg;
  58. unsigned char Cont;

  59. unsigned char  BlinkOfNumber = 0;

  60. unsigned char DutyCycle;
  61. unsigned char Mode;
  62. unsigned char ChangeFlag = 1;

  63. unsigned char SaveFlag;
  64. unsigned int SaveDelay;

  65. unsigned char RunF;
  66. unsigned char WaitF;

  67. unsigned char SwF;

  68. /**
  69.   ****************************************************************
  70.   * @brief Main function.
  71.   * @par Parameters: None
  72.   * @retval void None
  73.   * @par Required preconditions: None
  74.   ****************************************************************
  75.   */
  76. void main(void)
  77. {
  78.   /* Configures clocks  Fmaster = 16MHz */
  79.   CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
  80.        
  81.   /* read light value */
  82.   DutyCycle = FLASH_ReadByte(FLASH_DATA_START_PHYSICAL_ADDRESS);
  83.   if (! ((DutyCycle >= MIN) && (DutyCycle <= MAX)))
  84.         {        DutyCycle = (5 * MIN) ;        }
  85.        
  86.   /* Configures GPIOs */
  87.   GPIO_Configuration();

  88.         /* init pb */
  89.   SwF =   FLASH_ReadByte(FLASH_DATA_START_PHYSICAL_ADDRESS+1);
  90.   if (SwF)
  91.           {
  92.                   GPIO_WriteHigh(LED_GPIO_PORT, SW_4);
  93.                         GPIO_WriteLow(LED_GPIO_PORT, SW_5);
  94.                 }
  95.     else       
  96.                 {
  97.                         GPIO_WriteLow(LED_GPIO_PORT, SW_4);
  98.                   GPIO_WriteHigh(LED_GPIO_PORT, SW_5);
  99.                 }


  100.         /* read switch mode */
  101.         if ( GPIO_ReadInputPin(KEY_GPIO_PORT, KEY_MODE))
  102.           {Mode = ON;}
  103.         else
  104.     {Mode = OFF;}

  105.         /* Initialize PWM */
  106.         PWM1_Init();

  107.   /* TIM4 configuration */
  108.   TIM4_Config();

  109.   /* enable interrupts */
  110.   enableInterrupts();

  111.   while(1)
  112.         {
  113.                 /* 键盘处理 */
  114.     RunTask(Key_thread,Task0_ID);
  115.    
  116.           /* 常闭键处理 */
  117.                 if (! GPIO_ReadInputPin(KEY_GPIO_PORT, KEY_TRIGGER))
  118.                         {
  119.                           if (Mode == RUN)   { Mode = WAIT; ChangeFlag = 1; }
  120.                    }
  121.                   else
  122.                   {
  123.                           if (Mode == WAIT)          {        Mode = RUN;        ChangeFlag = 1; }
  124.                         }
  125.                        
  126.                 /* 闪烁服务 */
  127.                 RunTask(Blink,Task1_ID);

  128.                 /* 模式服务 */
  129.                 if ((ChangeFlag == 1) && (BlinkOfNumber == 0))
  130.           {
  131.                         ChangeFlag = 0;
  132.                   if (Mode == OFF)
  133.                   {
  134.                           GPIO_WriteLow(LED_GPIO_PORT3, LED_RUN);
  135.                                 RunF = 0;                WaitF = 0;
  136.                                 GPIO_WriteLow(LED_GPIO_PORT2, LED_WAIT);
  137.                                 GPIO_WriteLow(LED_GPIO_PORT2, LED_RUN3);
  138.                           TIM1_CtrlPWMOutputs(DISABLE);
  139.                   }
  140.                   if (Mode == ON)         { Mode = RUN; }
  141.                   if (Mode == RUN)
  142.                   {
  143.                           GPIO_WriteHigh(LED_GPIO_PORT3, LED_RUN);
  144.                                 RunF = 1;                WaitF = 0;
  145.                                 GPIO_WriteHigh(LED_GPIO_PORT2, LED_WAIT);
  146.                                 GPIO_WriteHigh(LED_GPIO_PORT2, LED_RUN3);
  147.                           TIM1_CtrlPWMOutputs(ENABLE);
  148.                   }
  149.                   if (Mode == WAIT)
  150.                   {
  151.                           GPIO_WriteLow(LED_GPIO_PORT3, LED_RUN);
  152.                                 RunF = 0;                WaitF = 1;
  153.                                 GPIO_WriteLow(LED_GPIO_PORT2, LED_WAIT);
  154.                                 GPIO_WriteLow(LED_GPIO_PORT2, LED_RUN3);
  155.                           TIM1_CtrlPWMOutputs(DISABLE);
  156.                   }
  157.                        
  158.                         if (RunF || WaitF)
  159.                    { GPIO_WriteHigh(LED_GPIO_PORT, LED_RUN_OR_WAIT); }
  160.                         else
  161.                    { GPIO_WriteLow(LED_GPIO_PORT, LED_RUN_OR_WAIT);}
  162.                                   }
  163.                
  164.                
  165.                 RunTask(SwRead,Task2_ID);

  166.                 /* 存储服务 */
  167.                 if (SaveFlag == 1)
  168.                 {
  169.                         if (SaveDelay == 0 )
  170.                         {
  171.                                 Write_Byte(FLASH_DATA_START_PHYSICAL_ADDRESS,DutyCycle);
  172.                                 Write_Byte(FLASH_DATA_START_PHYSICAL_ADDRESS+1,SwF);
  173.                                 SaveFlag = 0;
  174.                         }
  175.                 }
  176.                
  177.          // RunTask(task0,Task1_ID);
  178.          // RunTask(task1,Task2_ID);
  179.   }
  180.        
  181. }

  182. /**
  183.   ******************************************************************
  184.   * @brief Toggle Sw switch
  185.   * @par Parameters: None
  186.   * @retval void None
  187.   * @par Required preconditions: None
  188.   ******************************************************************
  189.   */
  190. unsigned char SwRead(void)
  191. {
  192.         _BEGIN
  193.     if (GPIO_ReadInputPin(KEY_GPIO_PORT2, KEY_SW))
  194.                 {
  195.                       WaitX(20);
  196.                 if  (GPIO_ReadInputPin(KEY_GPIO_PORT2, KEY_SW))         SwEvent();
  197.                  }
  198.         _END
  199. }


  200. unsigned char task0(void)
  201. {
  202.         _BEGIN
  203.         while(1)
  204.         {
  205.                 WaitX(100);
  206.                 GPIO_WriteHigh(LED_GPIO_PORT,SW_4);
  207.                 WaitX(200);
  208.                 GPIO_WriteLow(LED_GPIO_PORT,SW_4);
  209.         }
  210.         _END
  211. }

  212. unsigned char task1(void)
  213. {
  214.         _BEGIN
  215.         while(1)
  216.         {
  217.                 WaitX(50);
  218.                 GPIO_WriteHigh(LED_GPIO_PORT,SW_5);
  219.                 WaitX(50);
  220.                 GPIO_WriteLow(LED_GPIO_PORT,SW_5);
  221.         }
  222.         _END
  223. }

  224. /**
  225.   ******************************************************************
  226.   * @brief Delay before completing the action
  227.   * @param[in] function action() to be performed once the delay past
  228.   * @param[in] None
  229.   * @retval void None
  230.   * @par Required preconditions: None
  231.   ******************************************************************
  232.   */
  233. unsigned char Key_thread(void)
  234. {
  235.   _BEGIN
  236.     KeyRead();
  237.     if (Trg)
  238.         {
  239.         WaitX(20);
  240.         KeyRead();
  241.         if(Cont)  
  242.          {
  243.          if ((Cont & KEY_PLUS) && (Mode == RUN))  { LightPlus(); }
  244.          if ((Cont & KEY_REDUCE) && (Mode == RUN))  { LightReduce(); }
  245.          if (Cont & KEY_POWER)   { PowerEvent(); }
  246.          }
  247.         }
  248.   _END
  249. }       

  250. /**
  251.   ******************************************************************
  252.   * @brief Delay before completing the action
  253.   * @param[in] function action() to be performed once the delay past
  254.   * @param[in] None
  255.   * @retval void None
  256.   * @par Required preconditions: None
  257.   ******************************************************************
  258.   */
  259. unsigned char Blink(void)
  260. {
  261.         _BEGIN
  262.         if (BlinkOfNumber > 0)
  263.         {
  264.                 WaitX(100);
  265.                 GPIO_WriteReverse(LED_GPIO_PORT, LED_WAIT);
  266.                 BlinkOfNumber--;
  267.         }
  268.         _END
  269. }


  270. /**
  271.   ***************************************************************
  272.   * @brief Configures GPIOs
  273.   * @par Parameters: None
  274.   * @retval void None
  275.   * @par Required preconditions: None
  276.   ***************************************************************
  277.   */
  278. void GPIO_Configuration(void)
  279. {
  280.   /* GPIOD reset */
  281.         GPIO_DeInit(LED_GPIO_PORT);
  282.         GPIO_DeInit(LED_GPIO_PORT2);
  283.         GPIO_DeInit(KEY_GPIO_PORT);
  284.        
  285.         GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS,GPIO_MODE_OUT_PP_LOW_FAST);
  286.         GPIO_Init(LED_GPIO_PORT2, (GPIO_Pin_TypeDef)LED_GPIO_PINS2,GPIO_MODE_OUT_PP_LOW_FAST);       
  287.         GPIO_Init(LED_GPIO_PORT3, (GPIO_Pin_TypeDef)LED_GPIO_PINS3,GPIO_MODE_OUT_PP_LOW_FAST);       
  288.        
  289.         GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_GPIO_PINS,GPIO_MODE_IN_PU_NO_IT);
  290.         GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_TRIGGER_PINS,GPIO_MODE_IN_PU_NO_IT);
  291.   GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_MODE_PINS,GPIO_MODE_IN_PU_NO_IT);
  292.   GPIO_Init(KEY_GPIO_PORT2, (GPIO_Pin_TypeDef)KEY_SW_PINS,GPIO_MODE_IN_PU_NO_IT);
  293.        
  294. }


  295. /**
  296.   *****************************************************************
  297.   * @brief  Configure TIM4 to generate an update interrupt each 1ms
  298.   * @param  None
  299.   * @retval None
  300.  *****************************************************************
  301.   */
  302. void TIM4_Config(void)
  303. {
  304.   /* TIM4 configuration:
  305.    - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
  306.    clock used is 16 MHz / 128 = 125 000 Hz
  307.   - With 125 000 Hz we can generate time base:
  308.       max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
  309.       min time base is 0.016 ms if TIM4_PERIOD = 1   --> (  1 + 1) / 125000 = 0.016 ms
  310.   - In this example we need to generate a time base equal to 1 ms
  311.    so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */

  312.   /* Time base configuration */
  313.   TIM4_TimeBaseInit(TIM4_PRESCALER_128, TIM4_PERIOD);
  314.   /* Clear TIM4 update flag */
  315.   TIM4_ClearFlag(TIM4_FLAG_UPDATE);
  316.   /* Enable update interrupt */
  317.   TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);

  318.   /* Enable TIM4 */
  319.   TIM4_Cmd(ENABLE);
  320. }

  321. /**
  322.   ********************************************************
  323.   * @brief  Decrements the TimingDelay variable.
  324.   * @param  None
  325.   * @retval None
  326.  ********************************************************
  327.   */
  328. void TimingDelay_Decrement(void)
  329. {  if (SaveDelay != 0x00) { SaveDelay--;} }

  330. /**
  331.   *****************************************************************
  332.   * @brief Initialize all the PWM Parameters
  333.   * @par Parameters: None
  334.   * @retval void None
  335.   * @par Required preconditions: None
  336.   *****************************************************************
  337.   */
  338. void PWM1_Init(void)
  339. {
  340.           /* PWM1 Mode configuration Channel2
  341.            * Duty Cycle = [TIM1_CCR2/(TIM1_ARR+1)]*100=50% */
  342.        
  343.                 TIM1_DeInit();
  344.                
  345.                 /* Time Base configuration */
  346.     /*
  347.                    TIM1_Prescaler = 1280   分频16/1280 = 12.5 KHz
  348.        TIM1_Period = 69     频率12.5K /(69+1) = 179Hz
  349.        TIM1_CounterMode = TIM1_COUNTERMODE_UP
  350.                          TIM1_RepetitionCounter = 0
  351.     */
  352.                 TIM1_TimeBaseInit(1280, TIM1_COUNTERMODE_UP, 69, 0);
  353.                
  354.                 /* Channel 2 Configuration in PWM mode */
  355.     /*
  356.        TIM1_OCMode = TIM1_OCMODE_PWM2
  357.        TIM1_OutputState = TIM1_OUTPUTSTATE_ENABLE
  358.        TIM1_OutputNState = TIM1_OUTPUTNSTATE_ENABLE
  359.        TIM1_Pulse = DutyCycle
  360.        TIM1_OCPolarity = TIM1_OCPOLARITY_LOW
  361.        TIM1_OCNPolarity = TIM1_OCNPOLARITY_HIGH
  362.        TIM1_OCIdleState = TIM1_OCIDLESTATE_SET
  363.        TIM1_OCNIdleState = TIM1_OCIDLESTATE_RESET
  364.     */
  365.                 TIM1_OC3Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_ENABLE, DutyCycle,
  366.                TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_HIGH, TIM1_OCIDLESTATE_SET,
  367.                TIM1_OCNIDLESTATE_RESET);
  368.                                                          
  369.     TIM1_OC4Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, DutyCycle, TIM1_OCPOLARITY_LOW,
  370.                TIM1_OCIDLESTATE_SET);
  371.                                                                        
  372.                 /* TIM1 counter enable */
  373.     TIM1_Cmd(ENABLE);
  374.                  
  375.                 /* TIM1 Main Output Enable */
  376.     TIM1_CtrlPWMOutputs(ENABLE);
  377. }


  378. /**
  379.   ***************************************************************
  380.   * @brief Set DutyCycle value
  381.   * @par Parameters: None
  382.   * @retval void None
  383.   * @par Required preconditions: None
  384.   ***************************************************************
  385.   */
  386. void SetTIM1_PWM_DutyCycle(uint16_t TIM1_Pulse)
  387. {
  388.         /* Set the Pulse value */
  389.         TIM1->CCR3H = (uint8_t)(TIM1_Pulse >> 8);
  390.         TIM1->CCR3L = (uint8_t)(TIM1_Pulse);
  391.         /* Set the Pulse value */
  392.         TIM1->CCR4H = (uint8_t)(TIM1_Pulse >> 8);
  393.         TIM1->CCR4L = (uint8_t)(TIM1_Pulse);
  394. }


  395. /**
  396.   ******************************************************************
  397.   * @brief Toggle Power switch
  398.   * @par Parameters: None
  399.   * @retval void None
  400.   * @par Required preconditions: None
  401.   ******************************************************************
  402.   */
  403. void KeyRead( void )
  404. {
  405.         //uint8_t ReadData  = (GPIO_ReadInputData(KEY_GPIO_PORT)^0xFF) & 0x0E ;
  406.         unsigned char ReadData  = (GPIO_ReadInputData(KEY_GPIO_PORT)^0xFF) & 0x0E ;
  407.         Trg = ReadData & (ReadData ^ Cont);      
  408.         Cont = ReadData;                 
  409. }


  410. /**
  411.   ******************************************************************
  412.   * @brief Toggle Power switch
  413.   * @par Parameters: None
  414.   * @retval void None
  415.   * @par Required preconditions: None
  416.   ******************************************************************
  417.   */
  418. void PowerEvent(void)
  419. {
  420.   if ( Mode == OFF )             { Mode = ON;  }
  421.         else             { Mode = OFF; }
  422.         ChangeFlag = 1;
  423. }

  424. /**
  425.   ****************************************************************
  426.   * @brief Configures clocks
  427.   * @par Parameters: None
  428.   * @retval void None
  429.   * @par Required preconditions: None
  430.   ****************************************************************
  431.   */
  432. void LightPlus(void)
  433. {
  434.             if (DutyCycle == MAX)
  435.             {
  436.                     if (BlinkOfNumber == 0)            {BlinkOfNumber = 16;}
  437.             }
  438.             else
  439.             {
  440.                     DutyCycle = (DutyCycle + STEP);
  441.                                 SetTIM1_PWM_DutyCycle(DutyCycle);
  442.                                 SaveFlag = 1;
  443.                                 SaveDelay = (60 * Sec);
  444.             }
  445. }

  446. /**
  447.   ****************************************************************
  448.   * @brief Configures clocks
  449.   * @par Parameters: None
  450.   * @retval void None
  451.   * @par Required preconditions: None
  452.   ****************************************************************
  453.   */
  454. void LightReduce(void)
  455. {
  456.                   if (DutyCycle == MIN)
  457.             {
  458.                     if (BlinkOfNumber == 0 )   {BlinkOfNumber = 16;}
  459.             }
  460.             else
  461.             {
  462.                     DutyCycle = (DutyCycle - STEP);
  463.                                 SetTIM1_PWM_DutyCycle(DutyCycle);
  464.                     SaveFlag = 1;
  465.                                 SaveDelay = (60 * Sec);
  466.             }
  467. }


  468. /**
  469.   ******************************************************************
  470.   * @brief Toggle Sw switch
  471.   * @par Parameters: None
  472.   * @retval void None
  473.   * @par Required preconditions: None
  474.   ******************************************************************
  475.   */
  476. void SwEvent(void)
  477. {
  478.   if ( Mode == ON )
  479.              {
  480.                          GPIO_WriteReverse(LED_GPIO_PORT, SW_4);
  481.                          GPIO_WriteReverse(LED_GPIO_PORT, SW_5);
  482.                          SwF = GPIO_ReadInputPin(LED_GPIO_PORT, SW_4);
  483.                          SaveFlag = 1;
  484.                          SaveDelay = (60 * Sec);
  485.                          }

  486. }

  487. /**
  488.   ******************************************************************
  489.   * @brief Write EEPROM by byte
  490.   * @param[address] Start address
  491.   * @param[Data] Data
  492.   * @retval void None
  493.   ******************************************************************
  494.   */

  495. void Write_Byte (unsigned int address,unsigned char Data)
  496. {   
  497.     FLASH->DUKR = 0xAE;
  498.     FLASH->DUKR = 0x56;
  499.     FLASH->CR2 = 0x00;
  500.     FLASH->NCR2 = 0xFF;
  501.     *((u8*)address) = Data;
  502.     FLASH->IAPSR = (u8)(~0x08);
  503. }




  504. #ifdef USE_FULL_ASSERT
  505. /**
  506.   * @brief  Reports the name of the source file and the source line number
  507.   *   where the assert_param error has occurred.
  508.   * @param file: pointer to the source file name
  509.   * @param line: assert_param error line source number
  510.   * @retval None
  511.   */
  512. void assert_failed(uint8_t* file, uint32_t line)
  513. {
  514.   /* User can add his own implementation to report the file name and line number,
  515.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  516.   /* Infinite loop */
  517.   while (1)
  518.   {
  519.   }
  520. }
  521. #endif
复制代码

出0入0汤圆

 楼主| 发表于 2013-8-16 15:55:42 | 显示全部楼层
holts2 发表于 2013-8-16 13:30
我在stm8s103使用库,用到, 编绎正常,但程序不能正常运行,不知从何查起

定时器中断代码在哪里呢?

出0入0汤圆

发表于 2013-8-16 21:09:36 | 显示全部楼层
smset 发表于 2013-8-16 15:55
定时器中断代码在哪里呢?

在中断文件中


  1. /**
  2.   * @brief Timer4 Update/Overflow Interrupt routine.
  3.   * @param  None
  4.   * @retval None
  5.   */
  6. INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
  7. {
  8.   /* In order to detect unexpected events during development,
  9.      it is recommended to set a breakpoint on the following instruction.
  10.         */
  11.         TimingDelay_Decrement();
  12.         UpdateTimers();
  13.   /* Cleat Interrupt Pending bit */
  14.   TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
  15.         }
复制代码

出0入0汤圆

 楼主| 发表于 2013-8-17 14:15:55 | 显示全部楼层
Key_thread, 这个任务怎么没while(1)呢,这样只能启动时运行一次就结束了任务。


出0入0汤圆

发表于 2013-8-18 13:32:57 | 显示全部楼层
收藏,以待学习

出0入0汤圆

发表于 2013-8-20 17:43:06 | 显示全部楼层
各位大侠,遇到需要挂起的任务怎么办呢?

出0入0汤圆

 楼主| 发表于 2013-8-20 18:49:44 | 显示全部楼层
bondxie3 发表于 2013-8-20 17:43
各位大侠,遇到需要挂起的任务怎么办呢?

把它的定时器值设为255即可挂起,设为0即可恢复。

出0入0汤圆

发表于 2013-8-21 09:18:02 | 显示全部楼层
谢谢smset楼主,一直在想有条件的启动或者挂起某个任务, 其实设置任务的定时器即可.

出0入0汤圆

发表于 2013-8-21 16:57:58 | 显示全部楼层
[code]
u8 TaskB(void)
{
_SS
        WaitX(100);
        LED_ON();
        WaitX(100);
        LED_OFF();       
_EE       
}

u8 TaskA(void)
{
_SS
        while(1)
        {
                if(Flag)
                {
                        Flag=0;
                        CallSub(TaskB);
                }
                //...其他操作       
        }
_EE       
}
[code]
大侠,请问这种写法对吗,怎么总是进入TaskB呢?

出0入0汤圆

发表于 2013-8-21 16:59:14 | 显示全部楼层
[code]
u8 TaskB(void)
{
_SS
        WaitX(100);
        LED_ON();
        WaitX(100);
        LED_OFF();       
_EE       
}

u8 TaskA(void)
{
_SS
        while(1)
        {
                if(Flag)
                {
                        Flag=0;
                        CallSub(TaskB);
                }
                //...其他操作       
        }
_EE       
}
[/ code]
再发

出0入0汤圆

发表于 2013-8-21 17:00:02 | 显示全部楼层
大侠们说的发代码方法不行啊

  1. u8 TaskB(void)
  2. {
  3. _SS
  4.         WaitX(100);
  5.         LED_ON();
  6.         WaitX(100);
  7.         LED_OFF();        
  8. _EE        
  9. }

  10. u8 TaskA(void)
  11. {
  12. _SS
  13.         while(1)
  14.         {
  15.                 if(Flag)
  16.                 {
  17.                         Flag=0;
  18.                         CallSub(TaskB);
  19.                 }
  20.                 //...其他操作        
  21.         }
  22. _EE        
  23. }
复制代码

出0入0汤圆

发表于 2013-8-21 17:01:38 | 显示全部楼层
呵呵,应该是这样啊.
[code]
代码
[/ code]
实际使用时去掉'/'后面的空格

出0入0汤圆

发表于 2013-8-23 10:56:14 | 显示全部楼层
671楼的调用没有问题,是TaskB变量没有设置成static引起的.
我觉得只要不跨越Wait类的操作,变量可为临时变量.

出0入0汤圆

 楼主| 发表于 2013-8-23 11:56:32 | 显示全部楼层
是的,楼上说的没错。 不过尽量采用静态变量,就可以避免这类问题。

出0入0汤圆

 楼主| 发表于 2013-8-23 12:18:47 | 显示全部楼层
bondxie3 发表于 2013-8-23 10:56
671楼的调用没有问题,是TaskB变量没有设置成static引起的.
我觉得只要不跨越Wait类的操作,变量可为临时变量 ...

建议用492楼的版本。 671楼的有潜在问题。

出0入10汤圆

发表于 2013-8-23 13:41:28 | 显示全部楼层
下次做东西的时候用用:)

出0入0汤圆

发表于 2013-8-30 14:27:07 | 显示全部楼层
smset 发表于 2013-8-17 14:15
Key_thread, 这个任务怎么没while(1)呢,这样只能启动时运行一次就结束了任务。

难怪编绎没报错,一切正常,就是不能用,原来是键盘

出0入0汤圆

发表于 2013-8-30 17:57:11 | 显示全部楼层
都快到700楼了,有没有详细测试过代码?
比如:
--------------------------------------------------------------------
unsigned char  task1(){
_SS
  while(1){
   WaitX(500);
   while(TIMEOUT); //这是某个应用操作的超时等待;
   RevBit(LED1_PORT, LED1_PIN);
  }
_EE
}

------------------------------------------------------------------

调度的时间变了。。。

出0入0汤圆

 楼主| 发表于 2013-8-30 18:31:42 | 显示全部楼层
WaitX(dtime) , dtime 必须小于255.

出0入0汤圆

 楼主| 发表于 2013-8-30 18:32:37 | 显示全部楼层
本帖最后由 smset 于 2013-8-30 18:37 编辑

--------------------------------------------------------------------
unsigned char  task1(){
_SS
  while(1){
   WaitX(250);
   WaitX(250);
   while(TIMEOUT); //这是某个应用操作的超时等待;
   RevBit(LED1_PORT, LED1_PIN);
  }
_EE
}
再试试看
------------------------------------------------------------------

另外,我很不建议你这里 while(TIMEOUT);

因为这个调度器不建议在任务里面死循环,不释放出去。如果所有任务都是协作式的,很可能这样做永远就在这里循环了。
--------------------------------------------------------------------
unsigned char  task1(){
_SS
  while(1){
   WaitX(250);
   WaitX(250);
   while(TIMEOUT){
      WaitX(0);
   }
   RevBit(LED1_PORT, LED1_PIN);
  }
_EE
}
------------------------------------------------------------------
你的逻辑,可以这样来做。

或者用信号量来实现,也是可以的。

出0入0汤圆

发表于 2013-9-2 08:18:11 | 显示全部楼层
smset 发表于 2013-8-30 18:32
--------------------------------------------------------------------
unsigned char  task1(){
_SS

while(TIMEOUT)
{
      WaitX(0);
}
这种方式有问题.  使用如下方式才行
do
{
     WaitX(0);
}while( TIMEOUT );

可以把这种方式定义成一个宏:
#define WaitUntil(CondExpr,Cyc)                \
                do                                        \
                {                                        \
                        WaitX(Cyc);                \
                }while( !(CondExpr) )

出0入0汤圆

发表于 2013-9-15 17:55:16 | 显示全部楼层
我也来一层,有机会了再研究。

出0入0汤圆

发表于 2013-9-16 08:47:07 | 显示全部楼层
个人觉得就是一个软timer,由于没有上下文切换导致"任务"不能while(),实时性很不强,实用性有待加强.

出0入0汤圆

发表于 2013-10-12 11:38:33 | 显示全部楼层
vc6.0好像不支持case __LINE__这种用法~~,提示“case expression not constant”

出0入0汤圆

 楼主| 发表于 2013-10-12 12:39:59 | 显示全部楼层
wswh2o 发表于 2013-10-12 11:38
vc6.0好像不支持case __LINE__这种用法~~,提示“case expression not constant”

支持的哦,你检查下是不是哪里设置有问题。

我以前就用过vc下编译protothread,可以参考这里:
http://www.amobbs.com/forum.php? ... ghlight=protothread
头像被屏蔽

出0入0汤圆

发表于 2013-10-15 23:13:54 | 显示全部楼层
smset 发表于 2013-10-12 12:39
支持的哦,你检查下是不是哪里设置有问题。

我以前就用过vc下编译protothread,可以参考这里:

楼主 有3个问题请教下:
1. 有3个任务,Task0 1ms 执行一次  Task1  3ms 执行一次  Task3  10ms 执行一次    会重叠    怎么处理好一点,


2.有4个任务,都是10ms执行周期    例如 Task0  执行一次后    10ms 后在执行Task0     10ms 执行一轮  怎么处理好一点,

出0入0汤圆

发表于 2013-10-15 23:36:29 来自手机 | 显示全部楼层
学习了…
来自:amoBBS 阿莫电子论坛 Windows Phone 7 客户端

出0入0汤圆

发表于 2013-10-17 21:34:29 | 显示全部楼层
smset 发表于 2012-12-21 11:57
综合这几天的讨论,先更新一版,仅供评测用:主要改动有: 1) 增加了RunTaskA宏,让前面的任务有优先执行 ...

mark        

出200入0汤圆

发表于 2013-10-18 11:27:41 来自手机 | 显示全部楼层
顶……………………

出0入0汤圆

发表于 2013-10-23 21:39:13 | 显示全部楼层
mark                                 

出0入0汤圆

发表于 2013-10-24 00:00:08 | 显示全部楼层
翻了几页还是不懂,先mark

出0入0汤圆

发表于 2013-10-24 09:08:07 | 显示全部楼层
太好了 哈哈 收藏!

出0入0汤圆

发表于 2013-10-25 12:10:18 | 显示全部楼层
本帖最后由 mathison 于 2013-10-25 12:11 编辑

谢谢 smset 大师 的分享
我正在尝试 将大师的调度器 改写一个已经量产的 电推剪的项目中
使用的 义隆 EM78P259 的ic

用了8年的汇编 尝试一下 C开发的痛苦和乐趣
如果改写后的代码能达到客户的要求  会和大家分享代码
目前在补C语言  关于c语言的书 smset大师有推荐吗 ?

出0入0汤圆

 楼主| 发表于 2013-10-25 13:10:38 | 显示全部楼层
mathison 发表于 2013-10-25 12:10
谢谢 smset 大师 的分享
我正在尝试 将大师的调度器 改写一个已经量产的 电推剪的项目中
使用的 义隆 EM7 ...

大师不敢当,我本是屌丝一枚。
我以前学习C语言,看的是谭浩强的书。

出0入0汤圆

 楼主| 发表于 2013-10-25 13:24:35 | 显示全部楼层
liujie14565 发表于 2013-10-15 23:13
楼主 有3个问题请教下:
1. 有3个任务,Task0 1ms 执行一次  Task1  3ms 执行一次  Task3  10ms 执行一次 ...

根据你的描述,总体上你还是在以定时器加状态机的思路在描述需求。

当然,也能用小小调度器任务机制来实现。只是不是真正多任务的思想。

如果你的任务是毫秒级的,那你应该把定时器中断周期减少到1毫秒,或者1毫秒以内。

比如:
第1点提到的3个任务,这个你就设计3个任务是可以的,或者简单点就设计一个任务,在这个任务里面实现三个任务的动作。

uchar TaskA(){
     static uchar count;
_SS
     count=0;
     while(1){
      WaitX(1);  //等待1毫秒,定时器中断时间为1毫秒      
      count++;
     }
     if ((count%1)==0)  task1proc();//任务1,1毫秒执行1次;
   if ((count%3)==0)  task2proc(); //任务2,3毫秒执行1次;
   if ((count%10)==0) task3proc();//任务3,10毫秒执行1次;
_EE
}


如果4个任务之间有先后等待关系,你也可以用一个把这4个的任务执行动作做成4个函数,
然后用一个任务函数来实现。

出0入4汤圆

发表于 2013-10-25 14:27:18 | 显示全部楼层
时间片,系统,MARK

出0入0汤圆

发表于 2013-10-25 21:36:43 | 显示全部楼层
smset 发表于 2013-8-30 18:32
--------------------------------------------------------------------
unsigned char  task1(){
_SS

嗯,这是可以也得到解决

但是这代码展开后应该是一个很长的函数调用关系

而不是真正意义的任务上调度器,当然也能完成

多任务,调度器应该做到任务有独立的空间,不限制

任务的操作。任务与任务独立,任务调度器隔离。

出0入0汤圆

发表于 2013-10-26 16:41:37 | 显示全部楼层
本帖最后由 mathison 于 2013-10-26 16:44 编辑

再次感谢 smset
附上我在 义隆单片机上的移植
芯片用的是 EM78P259N
编译环境 使用 eUIDE

比较BC的C编译器
居然不支持在中断中使用 数组
我想是因为 EM78P259N 中断没有自动保存 PSR (R4)寄存器的缘故

所以我汇编改写了 UpdateTimers()

同理因为数组的原因 RunTask(task0,0);也不能放在中断中调用, PS:工程中并没有给出 RunTask(task0,0);的汇编实现,有兴趣的朋友可以自行修改

//UpdateTimers();
        {
        unsigned char i;
        for(i=0;i<MAXTASKS ;i++)
        {
                _asm
                        {
                                MOV        A,@%timers
                                MOV        RSR,A
                                MOV        A,%i
                                ADD        RSR,A
                                MOV        A,@255
                                SUB        A,R0
                                JBC        0x03,0x00
                                JMP        asm_end
                                MOV        A,@1
                                SUB        A,R0
                                JBS        0x03,0x00
                                JMP        asm_end
                                MOV        R0,A       
                        asm_end:       
                        }
               
        }
        }

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2013-10-26 16:53:07 | 显示全部楼层
本人C开发新手
义隆的C编译器用起来真痛苦  
有用C做义隆单片机开发的朋友吗 请问你们用什么编译器

出0入0汤圆

发表于 2013-10-26 19:14:50 | 显示全部楼层
下载学习,感谢楼主!!

出0入0汤圆

发表于 2013-10-26 19:44:08 | 显示全部楼层
不明觉厉! 啊  

出0入0汤圆

发表于 2013-10-27 01:15:18 | 显示全部楼层
116 209 257 330 397 492 540 楼,楼主建议用492版。记号。

出0入0汤圆

 楼主| 发表于 2013-10-27 11:15:03 | 显示全部楼层
mathison 发表于 2013-10-26 16:41
再次感谢 smset
附上我在 义隆单片机上的移植
芯片用的是 EM78P259N

不用谢,很支持你的做法!

因为小小调度器本来就是为小资源单片机而生的。

义隆单片机是很流行的小资源单片机,把小小调度器移植到这类单片机上去,并供他人借鉴参考,也是很有意义的。

出0入4汤圆

发表于 2013-10-28 10:59:54 | 显示全部楼层
从1楼一只看到最后,眼镜都麻了。我也是用时间那本书里面的框架,自己稍微改了改,发现LZ这个更实用。准备作个交通灯的项目,移植过去试试看,用freescale的8位机

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-26 07:41

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

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