waking
发表于 2013-2-2 13:11:45
经典的调度器!!
freeboyxd
发表于 2013-2-21 20:27:10
实时性要求高的项目可能难以胜任了
Myauto123
发表于 2013-2-22 21:52:35
好东西,学习了。。。
liu110537
发表于 2013-2-26 12:23:11
下来研究研究
wxlcj
发表于 2013-2-27 09:21:46
楼主,新年过完了,可以继续讲课了。
Eagle_rxz
发表于 2013-3-4 22:59:18
任务调度,时间片轮询机制,不错,学习了
shuxmpx123
发表于 2013-3-5 16:00:38
本帖最后由 shuxmpx123 于 2013-3-5 16:07 编辑
呵呵楼主牛人啊,我正准备用protothread 的,看的一头雾水,正好看到你这个帖子,准备试用一下,不知楼主这个调度器跟protothread 相比如何,各有什么长短优缺啊··{:lol:}
shuxmpx123
发表于 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编译就没问题?
shuxmpx123
发表于 2013-3-6 16:45:15
找到报错的原因了,
unsigned char task0() 改成
unsigned char task0(void)就可以了。。。。
shuxmpx123
发表于 2013-3-6 17:29:07
本帖最后由 shuxmpx123 于 2013-3-6 17:30 编辑
谁能告诉我
unsigned chartask2(void){
_SS
while(1){
WaitX(100);
D3_BLINK();
}
_EE
}
比
unsigned chartask2(void){
D3_BLINK();
return 100;
}
这样写有什么好处, 这个我没太看懂,貌似 task2里面的函数都只运行了一次? 不是像系统那样一种死循环运行?
zj_871112
发表于 2013-3-6 20:56:25
很好啊~~正是需要
younge
发表于 2013-3-6 22:09:47
lihaolongli 发表于 2012-11-27 13:28 static/image/common/back.gif
前边的宏定义看的不大明白
我也是看不懂宏定义,找了点资料。看后好多了
shuxmpx123
发表于 2013-3-7 09:37:07
我觉得这个调度器不怎么样,
1、 任务多的时候UpdateTimers();这里面的步骤也不少;
2、 RunTaskA(task1,1); 。。。。。 RunTaskA(taskn,1); 在主函数的while(1)里面,每个任务也还是要依次检测看时间有没有到;
3、_SS_EEWaitX貌似没有必要,直接把任务函数放进去运行就可以了,如果是我没看懂这个地方的妙处,请大家指正;
下面的程序是我现在用的,感觉调度执行的步骤或许比楼主这个执行步骤更少:
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 == 0128ms
{
sys.task_128ms++;
if ((sys._32ms&0x07) == 0) // %8 == 0256ms
{
sys.task_256ms++;
if (sys._32ms&0x0F) // %16 == 0512ms
{
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;
}
}
pxq8410
发表于 2013-3-28 12:20:03
学习,任务调度
bondxie3
发表于 2013-4-7 16:40:23
一口气看完整个帖子,获益良多!希望这个调度器越来越好!
LearningASM
发表于 2013-4-8 08:24:34
由状态机到学习任务调度{:time:}
renwocai
发表于 2013-4-8 12:56:17
smset 发表于 2012-12-21 11:57 static/image/common/back.gif
综合这几天的讨论,先更新一版,仅供评测用:主要改动有: 1) 增加了RunTaskA宏,让前面的任务有优先执行 ...
我把这段程序手式展开看了几遍,还是有些疑问,请楼主及各位高手能解释下
1.信号量部分的宏定义了但后面都没有用到,可以直接注释掉吧?//#define SEM unsigned int
//初始化信号量
//#define InitSem(sem) sem=0;
//等待信号量
//#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
//等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
//#define WaitSemX(sem,tickets)do { sem=tickets+1; WaitX(0); if(sem>1){ sem--;return 1;} } while(0);
//发送信号量
//#define SendSem(sem)do {sem=0;} while(0);2.任务函数的展开,如下unsigned chartask1()
{
static unsigned char _lc;
switch(_lc)
{
default:while(1)
{
do {_lc=__LINE__+((__LINE__%256)==0); return 100 ;}
while(0);
case __LINE__+((__LINE__%256)==0):;
LED1=!LED1;
};
}; _lc=0; return 255;
}while(1) 的作用范围跨过了case __LINE__+((__LINE__%256)==0),但while(1)的执行条件是default,而default与case __LINE__+((__LINE__%256)==0)应该是并列的啊,这段代码应该是怎样执行的?或者说,default与case之间应该是完整的代码吧,怎么就少了一个大括号呢?
bondxie3
发表于 2013-4-9 11:35:10
renwocai 发表于 2013-4-8 12:56 static/image/common/back.gif
我把这段程序手式展开看了几遍,还是有些疑问,请楼主及各位高手能解释下
1.信号量部分的宏定义了但后 ...
要结合RunTask宏展开分析!
renwocai
发表于 2013-4-9 15:52:31
bondxie3 发表于 2013-4-9 11:35 static/image/common/back.gif
要结合RunTask宏展开分析!
谢谢回复,task1()不解决,RunTask就更没法看啦。
renwocai
发表于 2013-4-10 11:17:44
又看了几天,终于明白啦,原来while(1)的作用是执行完后一个case再强行拉回来记录一次行号。
现在还有一个问题,信号量是怎么使用的?能否给个简单的例程?
himm007
发表于 2013-4-10 15:33:00
smset 发表于 2013-1-6 18:30 static/image/common/back.gif
嗯,您说的很有道理。
可能本帖中有部分回帖认为: 小小调度器是 把时间片调度和protothread结合起来的 ...
“必须用的cpu(无法改换),仅仅只有512字节RAM, 8K字节ROM,而且我希望它干更多的事情。 ”
================================================================
闲逛的时候看到这么精彩的帖子,真实佩服各路高手。
不过我的看法是,
1,虽然小小调度器很精简,但它的代码只占整个系统的百分之一,再精简都会被其余的任务代码冗余掉。,
2,按照时间片的方式顺序调度各个任务,会打断任务的执行环境,编程时要实时考虑访问的内存是不是会被其它的任务修改,调度器很优美,但无疑会给开发者带来额外的困扰。
3,我还是倾向于使用状态机的方式,顺序处理各个任务,优先级高的任务多分配些状态,优先级低的少分配些。而且各个状态的执行函数都是在同一级,因此可以节省很多可贵的栈空间。
8K ROM,512Byte 也够用了。
fqc168
发表于 2013-4-10 17:48:09
我看了两天protothread,觉得还是使用状态机比较合适,明白了事,C语言就是追求简单易读,宏隐含太多东西!
smset
发表于 2013-4-10 18:09:09
himm007 发表于 2013-4-10 15:33 static/image/common/back.gif
“必须用的cpu(无法改换),仅仅只有512字节RAM, 8K字节ROM,而且我希望它干更多的事情。 ”
========= ...
1,虽然小小调度器很精简,但它的代码只占整个系统的百分之一,再精简都会被其余的任务代码冗余掉。,
小小调度器除了本身小巧外,最大的用处是通过这个调度框架,写出的代码反而比状态机还省CPU资源.所以前面说" 比裸奔还省资源 " ,就是这个意思.
2,按照时间片的方式顺序调度各个任务,会打断任务的执行环境,编程时要实时考虑访问的内存是不是会被其它的任务修改,调度器很优美,但无疑会给开发者带来额外的困扰。
你把小小调度器理解成抢占式多任务了, 但小小调度器不是抢占式多任务, 而是stackless的协作式调度, 不存在一个任务正在运行时,变量被其它的任务修改的可能性.也正是这样, 才会更加简化编程.
3,我还是倾向于使用状态机的方式,顺序处理各个任务,优先级高的任务多分配些状态,优先级低的少分配些。而且各个状态的执行函数都是在同一级,因此可以节省很多可贵的栈空间。
还是这个道理, 小小调度器是stackless的协作式调度器, 并不存在消耗更多的栈空间的问题.所以函数依然是同一级的.
smset
发表于 2013-4-10 18:12:37
当你习惯于状态机时,你可能感觉不出状态机的问题. 然而当你习惯于调度器以后,你才会感觉出状态机的问题.
同样的道理:
当你习惯开手动挡汽车的时候, 你并不觉得多大的不方便.
但是当你习惯开自动档汽车以后,你就再也不愿意开手动档汽车了.
jz701209李
发表于 2013-4-10 18:35:32
强帖留名。。。。。。
himm007
发表于 2013-4-11 14:14:49
帖子内容太多,你可以单独一个网页详细介绍这个么,个人网站或者新帖子什么的。
最好能把宏展开,这样好看懂些。
liyongl66
发表于 2013-4-12 16:27:29
很好的思路,多谢了!
meirenai
发表于 2013-4-14 23:53:07
标记。。。。.
皮爱了西
发表于 2013-4-15 15:02:34
收藏了先。
Hz01800475
发表于 2013-4-16 12:16:58
smset 发表于 2013-4-10 18:12 static/image/common/back.gif
当你习惯于状态机时,你可能感觉不出状态机的问题. 然而当你习惯于调度器以后,你才会感觉出状态机的问题.
...
楼主,能不能放出一个综合性的工程。比如有串口,IIC,SPI,按键的模板。
qingaixww
发表于 2013-4-16 22:47:47
有意义,高人!
zd305
发表于 2013-4-26 21:15:54
在PIC mplab xxc8 上编译,WaitX(50);出错,出错信息:constant expression required
jangyouhua
发表于 2013-5-6 21:48:52
smset思路很好!我在他的基础上改了一下,用于IAR c++ 编泽
有些没有完工!对共享变量加入临界保护!写的不好,不要扔砖头哦!
#ifndef WEEAOS_H
#define WEEAOS_H
#include "weea_cpu.h"
#define MAXTASKS 3u
#ifdefWEEA_GLOBALS
volatile INT16U weea_timers = {0};
#else
extern INT16U weea_timer;
#endif
#defineWEEA_BEGIN() static INT16U _lc; switch(_lc) { default:
#defineWEEA_END() } _lc = 0; return 0xffff;
#defineWaitX(ticks) do{_lc = __LINE__;return ticks;}while(0); case __LINE__:
#defineRunTask(TaskName,TaskID) do{if(weea_timers == 0) \
{\
INT16U _trvalue = TaskName(); \
OS_ENTER_CRITICAL(); \
weea_timers = _trvalue; \
OS_EXIT_CRITICAL(); \
}\
}while(0);
#define RunTaskEx(TaskName,TaskID) if(weea_timers == 0) \
{ \
INT16U _trvalue = TaskName(); \
OS_ENTER_CRITICAL(); \
weea_timers = _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 != 0) && (weea_timers != 0xffff)) weea_timers--;}} //一定要在中断中调用
//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信号量支持
typedefboolTmut;
#definemut_create(A,B) \
Tmut A = B
#define mut_create_extern(A) \
extern Tmut A
#defineSendMut(A) do{ (A) = true; }while(0);
#defineWaitMut(A) do{ WaitX(0); if(!(A)) return 1; }while(0);
#defineWaitMutX(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计数型信号量支持
typedefINT8UTsem;
#definesem_create(A,B) \
Tsem A = B
#define sem_create_extern(A) \
extern Tsem A
// 消息支持
#endif
jangyouhua
发表于 2013-5-6 22:03:07
稍修改了下,增加了注释:
#ifndef WEEAOS_H
#define WEEAOS_H
#include "weea_cpu.h"
#define MAXTASKS 3u
#ifdefWEEA_GLOBALS
volatile INT16U weea_timers = {0};
#else
extern INT16U weea_timer;
#endif
#defineWEEA_BEGIN() static INT16U _lc; switch(_lc) { default:
#defineWEEA_END() } _lc = 0; return 0xffff;
#defineWaitX(ticks) do{_lc = __LINE__;return ticks;}while(0); case __LINE__:
#defineRunTask(TaskName,TaskID) do{if(weea_timers == 0) \
{\
INT16U _trvalue = TaskName(); \
OS_ENTER_CRITICAL(); \
weea_timers = _trvalue; \
OS_EXIT_CRITICAL(); \
}\
}while(0);
#define RunTaskEx(TaskName,TaskID) if(weea_timers == 0) \
{ \
INT16U _trvalue = TaskName(); \
OS_ENTER_CRITICAL(); \
weea_timers = _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 != 0) && (weea_timers != 0xffff)) weea_timers--;}} //一定要在中断中调用
//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互斥型信号支持
typedefboolTmut;
#definemut_create(A,B) \
Tmut A = B
#define mut_create_extern(A) \
extern Tmut A
#defineSendMut(A) do{ (A) = true; }while(0);
#defineWaitMut(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 : 等到超时
#defineWaitMutX(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计数型信号量支持
typedefINT8UTsem;
#definesem_create(A,B) \
Tsem A = B
#define sem_create_extern(A) \
extern Tsem A
// 消息支持
#endif
jangyouhua
发表于 2013-5-6 22:16:31
用了n多RTOS,protothread确实叫人惊叹!如果测试没问题,可以支持消息、邮箱,以及类似keil RTX中的event事件!
jangyouhua
发表于 2013-5-6 22:53:32
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H
#include "weea_cpu.h"
#define MAXTASKS 3u
#ifdefWEEA_GLOBALS
volatile INT16U weea_timers = {0};
#else
extern INT16U weea_timer;
#endif
#defineWEEA_BEGIN() static INT16U _lc; switch(_lc) { default:
#defineWEEA_END() } _lc = 0; return 0xffff;
#defineWaitX(ticks) do{_lc = __LINE__;return ticks;}while(0); case __LINE__:
#defineRunTask(TaskName,TaskID) do{if(weea_timers == 0) \
{\
INT16U _trvalue = TaskName(); \
OS_ENTER_CRITICAL(); \
weea_timers = _trvalue; \
OS_EXIT_CRITICAL(); \
}\
}while(0);
#define RunTaskEx(TaskName,TaskID) if(weea_timers == 0) \
{ \
INT16U _trvalue = TaskName(); \
OS_ENTER_CRITICAL(); \
weea_timers = _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 != 0) && (weea_timers != 0xffff)) weea_timers--;}} //一定要在中断中调用
//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互斥型信号支持
typedefboolTmut;
#definemut_create(A,B) \
Tmut A = B
#define mut_create_extern(A) \
extern Tmut A
#defineSendMut(A) do{ (A) = true; }while(0);
#defineWaitMut(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 : 等到超时
#defineWaitMutX(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计数型信号支持
typedefINT8UTsem;
#definesem_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);
// 消息、邮箱支持
typedefINT8UTmsg;
#definemsg_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
eddia2012
发表于 2013-5-11 17:50:10
{:smile:}这个已用了好几个案子的开发了,它对C编译器适应性很强!
smset
发表于 2013-5-14 17:03:22
jangyouhua 发表于 2013-5-6 22:53 static/image/common/back.gif
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H
修改得好,期待能进一步完善和优化。
foxpro2005
发表于 2013-5-15 00:23:02
本帖最后由 foxpro2005 于 2013-5-15 00:30 编辑
jangyouhua 发表于 2013-5-6 22:53 static/image/common/back.gif
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H
互斥信号------ 这一部分好像有点问题....
WaitMut(A) do{ WaitX(0); if(!(A)) return 1; (A)=false; }while(0);
maimaige
发表于 2013-5-22 10:24:00
小 调度器 mark一下
Hz01800475
发表于 2013-5-24 14:39:43
eddia2012 发表于 2013-5-11 17:50 static/image/common/back.gif
这个已用了好几个案子的开发了,它对C编译器适应性很强!
{:smile:} 我现在在用你的代码,Task_event_wait(D_wait_ever); #define D_wait_ever ((u8)-1)这个宏是什么作用。
Hz01800475
发表于 2013-5-24 14:50:54
eddia2012 发表于 2013-5-11 17:50 static/image/common/back.gif
这个已用了好几个案子的开发了,它对C编译器适应性很强!
Task2_display() 这个函数没看懂, if(task_Wait_flag)什么意思啊。
{
Task_subCall(subtask);
}
Hz01800475
发表于 2013-5-24 15:45:28
eddia2012 发表于 2012-12-16 22:34 static/image/common/back.gif
希望加入事件触发优化。
你的代码加了吧。
安心
发表于 2013-6-12 08:44:15
{:smile:}不错
BruceZeng
发表于 2013-6-25 16:48:19
protothread
AIHHLI
发表于 2013-6-26 10:35:24
研究了一会,搞懂了。
真的很巧妙,赞一个。
看不懂的童鞋可以从楼主位那段代码开始,关键是task2,手动将宏展开,你将看到一种switch的变态用法,然后原理一目了然。__LINE__是语句所在的行号。
实际上在函数遇到延时返回前做了两件事:设置延时时间,设置状态变量lc,使得第二次进入函数时得到正确的跳转。
lovemini
发表于 2013-7-10 16:40:32
jangyouhua 发表于 2013-5-6 22:53 static/image/common/back.gif
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H
能提供weea_cpu.h 的代码吗?
tom_flag
发表于 2013-7-31 20:55:52
支持。。谢谢分享哈..调度器博大精深哈~~
smset
发表于 2013-7-31 22:59:23
#include <stc89c51.h>
/****小小调度器开始**********************************************/
#define MAXTASKS 3
volatile unsigned char timers;
#define _SS static unsigned char _lc; switch(_lc){default:
#define _EE ;}; _lc=0; return 255;
#define WaitX(tickets)do {_lc=__LINE__; return tickets ;} while(0); case __LINE__:
#define RunTask(TaskName,TaskID) do { if (timers==0) timers=TaskName(); }while(0);
#define RunTaskA(TaskName,TaskID) { if (timers==0) {timers=TaskName(); continue;} } //前面的任务优先保证执行
#define CallSub(SubTaskName) do {unsigned char currdt; _lc=__LINE__; return 0; case __LINE__:currdt=SubTaskName(); if(currdt!=255) return currdt;} while(0);
#define UpdateTimers() {unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers!=0)&&(timers!=255)) timers--;}}
#define SEM unsigned int
//初始化信号量
#define InitSem(sem) sem=0;
//等待信号量
#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
//等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
#define WaitSemX(sem,tickets)do { sem=tickets+1; WaitX(0); if(sem>1){ sem--;return 1;} } while(0);
//发送信号量
#define SendSem(sem)do {sem=0;} while(0);
/*****小小调度器结束*******************************************************/
sbit LED1 = P2^1;
sbit LED2 = P2^2;
sbit LED0 = P2^5;
unsigned char task0(){
_SS
while(1){
WaitX(50);
LED0=!LED0;
}
_EE
}
unsigned chartask1(){
_SS
while(1){
WaitX(100);
LED1=!LED1;
}
_EE
}
unsigned chartask2(){
_SS
while(1){
WaitX(100);
LED2=!LED2;
}
_EE
}
void InitT0()
{
TMOD = 0x21;
IE |= 0x82;// 12t
TL0=0Xff;
TH0=0XDB;
TR0 = 1;
}
void INTT0(void) interrupt 1 using 1
{
TL0=0Xff; //10ms 重装
TH0=0XDB;//b7;
UpdateTimers();
RunTask(task0,0);//任务0具有精确按时获得执行的权限,建议:task0每次执行消耗时间<0.5个 ticket
}
void main()
{
InitT0();
while(1){
//RunTask(task0,0);
RunTaskA(task1,1);//任务1具有比任务2高的运行权限
RunTaskA(task2,2);//任务2具有低的运行权限
}
}
liufabing
发表于 2013-8-1 17:20:57
Mark,学习
liufabing
发表于 2013-8-3 01:08:05
656楼的代码08行
#define _EE ;}; _lc=0; return 255;
后面的_lc=0; return 255;
程序不会运行这2句,不知道有什么作用?
rossih
发表于 2013-8-14 09:05:06
不是跟时间触发嵌入式系统那本书里的一样么?
smset
发表于 2013-8-14 09:57:08
rossih 发表于 2013-8-14 09:05 static/image/common/back.gif
不是跟时间触发嵌入式系统那本书里的一样么?
根本不一样,没有可比性。
holts2
发表于 2013-8-16 11:03:20
smset 发表于 2013-8-14 09:57 static/image/common/back.gif
根本不一样,没有可比性。
如果程序的行数超过255行,程序可以正常运行吗 ?
smset
发表于 2013-8-16 13:21:32
holts2 发表于 2013-8-16 11:03 static/image/common/back.gif
如果程序的行数超过255行,程序可以正常运行吗 ?
可以正常运行的。
holts2
发表于 2013-8-16 13:30:07
smset 发表于 2013-8-16 13:21 static/image/common/back.gif
可以正常运行的。
我在stm8s103使用库,用到, 编绎正常,但程序不能正常运行,不知从何查起
#include "ptask.h"
#include "stm8s.h"
#define LED_GPIO_PORT(GPIOA)
#define LED_GPIO_PINS(GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)
#define SW_4GPIO_PIN_1
#define SW_5GPIO_PIN_2
#define LED_RUN_OR_WAIT GPIO_PIN_3
#define LED_GPIO_PORT2 (GPIOC)
#define LED_GPIO_PINS2 (GPIO_PIN_5 | GPIO_PIN_6)
#define LED_WAIT GPIO_PIN_5
#define LED_RUN3 GPIO_PIN_6
#define LED_GPIO_PORT3 (GPIOD)
#define LED_GPIO_PINS3 (GPIO_PIN_6)
#define LED_RUN GPIO_PIN_6
#define KEY_GPIO_PORT(GPIOD)
#define KEY_GPIO_PINS(GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 )
#define KEY_POWER GPIO_PIN_1
#define KEY_REDUCE GPIO_PIN_2
#define KEY_PLUSGPIO_PIN_3
#define KEY_MODE_PINS (GPIO_PIN_4)
#define KEY_MODE GPIO_PIN_4
#define KEY_TRIGGER_PINS (GPIO_PIN_5)
#define KEY_TRIGGERGPIO_PIN_5
#define KEY_GPIO_PORT2(GPIOC)
#define KEY_SW_PINS (GPIO_PIN_7)
#define KEY_SW GPIO_PIN_7
#define MilliSec 1
#define Sec 1000
#define STEP 5 //约5%
#define MAX 70//100%
#define MIN 15//约21%
#define OFF 0
#define ON 1
#define RUN 2
#define WAIT 3
#define TIM4_PERIOD 124 //1ms定时
void GPIO_Configuration(void);
void TIM4_Config(void);
void TimingDelay_Decrement(void);
void PWM1_Init(void);
void SetTIM1_PWM_DutyCycle(uint16_t TIM1_Pulse);
unsigned char Blink(void);
unsigned char SwRead(void);
void KeyRead(void);
unsigned char Key_thread(void);
void LightReduce(void);
void LightPlus(void);
void PowerEvent(void);
void SwEvent(void);
void Write_Byte (unsigned int address,unsigned char Data);
unsigned char task0(void);
unsigned char task1(void);
/* Private functions -------------------------------------------*/
/* Global variables --------------------------------------------*/
volatile unsigned char timers={0};
unsigned char Trg;
unsigned char Cont;
unsigned charBlinkOfNumber = 0;
unsigned char DutyCycle;
unsigned char Mode;
unsigned char ChangeFlag = 1;
unsigned char SaveFlag;
unsigned int SaveDelay;
unsigned char RunF;
unsigned char WaitF;
unsigned char SwF;
/**
****************************************************************
* @brief Main function.
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
****************************************************************
*/
void main(void)
{
/* Configures clocksFmaster = 16MHz */
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
/* read light value */
DutyCycle = FLASH_ReadByte(FLASH_DATA_START_PHYSICAL_ADDRESS);
if (! ((DutyCycle >= MIN) && (DutyCycle <= MAX)))
{ DutyCycle = (5 * MIN) ; }
/* Configures GPIOs */
GPIO_Configuration();
/* init pb */
SwF = FLASH_ReadByte(FLASH_DATA_START_PHYSICAL_ADDRESS+1);
if (SwF)
{
GPIO_WriteHigh(LED_GPIO_PORT, SW_4);
GPIO_WriteLow(LED_GPIO_PORT, SW_5);
}
else
{
GPIO_WriteLow(LED_GPIO_PORT, SW_4);
GPIO_WriteHigh(LED_GPIO_PORT, SW_5);
}
/* read switch mode */
if ( GPIO_ReadInputPin(KEY_GPIO_PORT, KEY_MODE))
{Mode = ON;}
else
{Mode = OFF;}
/* Initialize PWM */
PWM1_Init();
/* TIM4 configuration */
TIM4_Config();
/* enable interrupts */
enableInterrupts();
while(1)
{
/* 键盘处理 */
RunTask(Key_thread,Task0_ID);
/* 常闭键处理 */
if (! GPIO_ReadInputPin(KEY_GPIO_PORT, KEY_TRIGGER))
{
if (Mode == RUN) { Mode = WAIT; ChangeFlag = 1; }
}
else
{
if (Mode == WAIT) { Mode = RUN; ChangeFlag = 1; }
}
/* 闪烁服务 */
RunTask(Blink,Task1_ID);
/* 模式服务 */
if ((ChangeFlag == 1) && (BlinkOfNumber == 0))
{
ChangeFlag = 0;
if (Mode == OFF)
{
GPIO_WriteLow(LED_GPIO_PORT3, LED_RUN);
RunF = 0; WaitF = 0;
GPIO_WriteLow(LED_GPIO_PORT2, LED_WAIT);
GPIO_WriteLow(LED_GPIO_PORT2, LED_RUN3);
TIM1_CtrlPWMOutputs(DISABLE);
}
if (Mode == ON) { Mode = RUN; }
if (Mode == RUN)
{
GPIO_WriteHigh(LED_GPIO_PORT3, LED_RUN);
RunF = 1; WaitF = 0;
GPIO_WriteHigh(LED_GPIO_PORT2, LED_WAIT);
GPIO_WriteHigh(LED_GPIO_PORT2, LED_RUN3);
TIM1_CtrlPWMOutputs(ENABLE);
}
if (Mode == WAIT)
{
GPIO_WriteLow(LED_GPIO_PORT3, LED_RUN);
RunF = 0; WaitF = 1;
GPIO_WriteLow(LED_GPIO_PORT2, LED_WAIT);
GPIO_WriteLow(LED_GPIO_PORT2, LED_RUN3);
TIM1_CtrlPWMOutputs(DISABLE);
}
if (RunF || WaitF)
{ GPIO_WriteHigh(LED_GPIO_PORT, LED_RUN_OR_WAIT); }
else
{ GPIO_WriteLow(LED_GPIO_PORT, LED_RUN_OR_WAIT);}
}
RunTask(SwRead,Task2_ID);
/* 存储服务 */
if (SaveFlag == 1)
{
if (SaveDelay == 0 )
{
Write_Byte(FLASH_DATA_START_PHYSICAL_ADDRESS,DutyCycle);
Write_Byte(FLASH_DATA_START_PHYSICAL_ADDRESS+1,SwF);
SaveFlag = 0;
}
}
// RunTask(task0,Task1_ID);
// RunTask(task1,Task2_ID);
}
}
/**
******************************************************************
* @brief Toggle Sw switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
unsigned char SwRead(void)
{
_BEGIN
if (GPIO_ReadInputPin(KEY_GPIO_PORT2, KEY_SW))
{
WaitX(20);
if(GPIO_ReadInputPin(KEY_GPIO_PORT2, KEY_SW)) SwEvent();
}
_END
}
unsigned char task0(void)
{
_BEGIN
while(1)
{
WaitX(100);
GPIO_WriteHigh(LED_GPIO_PORT,SW_4);
WaitX(200);
GPIO_WriteLow(LED_GPIO_PORT,SW_4);
}
_END
}
unsigned char task1(void)
{
_BEGIN
while(1)
{
WaitX(50);
GPIO_WriteHigh(LED_GPIO_PORT,SW_5);
WaitX(50);
GPIO_WriteLow(LED_GPIO_PORT,SW_5);
}
_END
}
/**
******************************************************************
* @brief Delay before completing the action
* @param function action() to be performed once the delay past
* @param None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
unsigned char Key_thread(void)
{
_BEGIN
KeyRead();
if (Trg)
{
WaitX(20);
KeyRead();
if(Cont)
{
if ((Cont & KEY_PLUS) && (Mode == RUN)){ LightPlus(); }
if ((Cont & KEY_REDUCE) && (Mode == RUN)){ LightReduce(); }
if (Cont & KEY_POWER) { PowerEvent(); }
}
}
_END
}
/**
******************************************************************
* @brief Delay before completing the action
* @param function action() to be performed once the delay past
* @param None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
unsigned char Blink(void)
{
_BEGIN
if (BlinkOfNumber > 0)
{
WaitX(100);
GPIO_WriteReverse(LED_GPIO_PORT, LED_WAIT);
BlinkOfNumber--;
}
_END
}
/**
***************************************************************
* @brief Configures GPIOs
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
***************************************************************
*/
void GPIO_Configuration(void)
{
/* GPIOD reset */
GPIO_DeInit(LED_GPIO_PORT);
GPIO_DeInit(LED_GPIO_PORT2);
GPIO_DeInit(KEY_GPIO_PORT);
GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(LED_GPIO_PORT2, (GPIO_Pin_TypeDef)LED_GPIO_PINS2,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(LED_GPIO_PORT3, (GPIO_Pin_TypeDef)LED_GPIO_PINS3,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_GPIO_PINS,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_TRIGGER_PINS,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_MODE_PINS,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(KEY_GPIO_PORT2, (GPIO_Pin_TypeDef)KEY_SW_PINS,GPIO_MODE_IN_PU_NO_IT);
}
/**
*****************************************************************
* @briefConfigure TIM4 to generate an update interrupt each 1ms
* @paramNone
* @retval None
*****************************************************************
*/
void TIM4_Config(void)
{
/* TIM4 configuration:
- TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
clock used is 16 MHz / 128 = 125 000 Hz
- With 125 000 Hz we can generate time base:
max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
min time base is 0.016 ms if TIM4_PERIOD = 1 --> (1 + 1) / 125000 = 0.016 ms
- In this example we need to generate a time base equal to 1 ms
so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */
/* Time base configuration */
TIM4_TimeBaseInit(TIM4_PRESCALER_128, TIM4_PERIOD);
/* Clear TIM4 update flag */
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
/* Enable update interrupt */
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
/* Enable TIM4 */
TIM4_Cmd(ENABLE);
}
/**
********************************************************
* @briefDecrements the TimingDelay variable.
* @paramNone
* @retval None
********************************************************
*/
void TimingDelay_Decrement(void)
{if (SaveDelay != 0x00) { SaveDelay--;} }
/**
*****************************************************************
* @brief Initialize all the PWM Parameters
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
*****************************************************************
*/
void PWM1_Init(void)
{
/* PWM1 Mode configuration Channel2
* Duty Cycle = *100=50% */
TIM1_DeInit();
/* Time Base configuration */
/*
TIM1_Prescaler = 1280 分频16/1280 = 12.5 KHz
TIM1_Period = 69 频率12.5K /(69+1) = 179Hz
TIM1_CounterMode = TIM1_COUNTERMODE_UP
TIM1_RepetitionCounter = 0
*/
TIM1_TimeBaseInit(1280, TIM1_COUNTERMODE_UP, 69, 0);
/* Channel 2 Configuration in PWM mode */
/*
TIM1_OCMode = TIM1_OCMODE_PWM2
TIM1_OutputState = TIM1_OUTPUTSTATE_ENABLE
TIM1_OutputNState = TIM1_OUTPUTNSTATE_ENABLE
TIM1_Pulse = DutyCycle
TIM1_OCPolarity = TIM1_OCPOLARITY_LOW
TIM1_OCNPolarity = TIM1_OCNPOLARITY_HIGH
TIM1_OCIdleState = TIM1_OCIDLESTATE_SET
TIM1_OCNIdleState = TIM1_OCIDLESTATE_RESET
*/
TIM1_OC3Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_ENABLE, DutyCycle,
TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_HIGH, TIM1_OCIDLESTATE_SET,
TIM1_OCNIDLESTATE_RESET);
TIM1_OC4Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, DutyCycle, TIM1_OCPOLARITY_LOW,
TIM1_OCIDLESTATE_SET);
/* TIM1 counter enable */
TIM1_Cmd(ENABLE);
/* TIM1 Main Output Enable */
TIM1_CtrlPWMOutputs(ENABLE);
}
/**
***************************************************************
* @brief Set DutyCycle value
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
***************************************************************
*/
void SetTIM1_PWM_DutyCycle(uint16_t TIM1_Pulse)
{
/* Set the Pulse value */
TIM1->CCR3H = (uint8_t)(TIM1_Pulse >> 8);
TIM1->CCR3L = (uint8_t)(TIM1_Pulse);
/* Set the Pulse value */
TIM1->CCR4H = (uint8_t)(TIM1_Pulse >> 8);
TIM1->CCR4L = (uint8_t)(TIM1_Pulse);
}
/**
******************************************************************
* @brief Toggle Power switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
void KeyRead( void )
{
//uint8_t ReadData= (GPIO_ReadInputData(KEY_GPIO_PORT)^0xFF) & 0x0E ;
unsigned char ReadData= (GPIO_ReadInputData(KEY_GPIO_PORT)^0xFF) & 0x0E ;
Trg = ReadData & (ReadData ^ Cont);
Cont = ReadData;
}
/**
******************************************************************
* @brief Toggle Power switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
void PowerEvent(void)
{
if ( Mode == OFF ) { Mode = ON;}
else { Mode = OFF; }
ChangeFlag = 1;
}
/**
****************************************************************
* @brief Configures clocks
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
****************************************************************
*/
void LightPlus(void)
{
if (DutyCycle == MAX)
{
if (BlinkOfNumber == 0) {BlinkOfNumber = 16;}
}
else
{
DutyCycle = (DutyCycle + STEP);
SetTIM1_PWM_DutyCycle(DutyCycle);
SaveFlag = 1;
SaveDelay = (60 * Sec);
}
}
/**
****************************************************************
* @brief Configures clocks
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
****************************************************************
*/
void LightReduce(void)
{
if (DutyCycle == MIN)
{
if (BlinkOfNumber == 0 ) {BlinkOfNumber = 16;}
}
else
{
DutyCycle = (DutyCycle - STEP);
SetTIM1_PWM_DutyCycle(DutyCycle);
SaveFlag = 1;
SaveDelay = (60 * Sec);
}
}
/**
******************************************************************
* @brief Toggle Sw switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
void SwEvent(void)
{
if ( Mode == ON )
{
GPIO_WriteReverse(LED_GPIO_PORT, SW_4);
GPIO_WriteReverse(LED_GPIO_PORT, SW_5);
SwF = GPIO_ReadInputPin(LED_GPIO_PORT, SW_4);
SaveFlag = 1;
SaveDelay = (60 * Sec);
}
}
/**
******************************************************************
* @brief Write EEPROM by byte
* @param Start address
* @param Data
* @retval void None
******************************************************************
*/
void Write_Byte (unsigned int address,unsigned char Data)
{
FLASH->DUKR = 0xAE;
FLASH->DUKR = 0x56;
FLASH->CR2 = 0x00;
FLASH->NCR2 = 0xFF;
*((u8*)address) = Data;
FLASH->IAPSR = (u8)(~0x08);
}
#ifdef USE_FULL_ASSERT
/**
* @briefReports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
smset
发表于 2013-8-16 15:55:42
holts2 发表于 2013-8-16 13:30 static/image/common/back.gif
我在stm8s103使用库,用到, 编绎正常,但程序不能正常运行,不知从何查起
定时器中断代码在哪里呢?
holts2
发表于 2013-8-16 21:09:36
smset 发表于 2013-8-16 15:55 static/image/common/back.gif
定时器中断代码在哪里呢?
在中断文件中
/**
* @brief Timer4 Update/Overflow Interrupt routine.
* @paramNone
* @retval None
*/
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
TimingDelay_Decrement();
UpdateTimers();
/* Cleat Interrupt Pending bit */
TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
}
smset
发表于 2013-8-17 14:15:55
Key_thread, 这个任务怎么没while(1)呢,这样只能启动时运行一次就结束了任务。
raosibin
发表于 2013-8-18 13:32:57
收藏,以待学习
bondxie3
发表于 2013-8-20 17:43:06
各位大侠,遇到需要挂起的任务怎么办呢?
smset
发表于 2013-8-20 18:49:44
bondxie3 发表于 2013-8-20 17:43 static/image/common/back.gif
各位大侠,遇到需要挂起的任务怎么办呢?
把它的定时器值设为255即可挂起,设为0即可恢复。
bondxie3
发表于 2013-8-21 09:18:02
谢谢smset楼主,一直在想有条件的启动或者挂起某个任务, 其实设置任务的定时器即可.
bondxie3
发表于 2013-8-21 16:57:58
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
}
大侠,请问这种写法对吗,怎么总是进入TaskB呢?
bondxie3
发表于 2013-8-21 16:59:14
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]
再发
bondxie3
发表于 2013-8-21 17:00:02
大侠们说的发代码方法不行啊
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
}
bondxie3
发表于 2013-8-21 17:01:38
呵呵,应该是这样啊.
代码
[/ code]
实际使用时去掉'/'后面的空格
bondxie3
发表于 2013-8-23 10:56:14
671楼的调用没有问题,是TaskB变量没有设置成static引起的.
我觉得只要不跨越Wait类的操作,变量可为临时变量.
smset
发表于 2013-8-23 11:56:32
是的,楼上说的没错。 不过尽量采用静态变量,就可以避免这类问题。
smset
发表于 2013-8-23 12:18:47
bondxie3 发表于 2013-8-23 10:56 static/image/common/back.gif
671楼的调用没有问题,是TaskB变量没有设置成static引起的.
我觉得只要不跨越Wait类的操作,变量可为临时变量 ...
建议用492楼的版本。 671楼的有潜在问题。
linbin250
发表于 2013-8-23 13:41:28
下次做东西的时候用用:)
holts2
发表于 2013-8-30 14:27:07
smset 发表于 2013-8-17 14:15 static/image/common/back.gif
Key_thread, 这个任务怎么没while(1)呢,这样只能启动时运行一次就结束了任务。
难怪编绎没报错,一切正常,就是不能用,原来是键盘
worldsing
发表于 2013-8-30 17:57:11
都快到700楼了,有没有详细测试过代码?
比如:
--------------------------------------------------------------------
unsigned chartask1(){
_SS
while(1){
WaitX(500);
while(TIMEOUT); //这是某个应用操作的超时等待;
RevBit(LED1_PORT, LED1_PIN);
}
_EE
}
------------------------------------------------------------------
调度的时间变了。。。
smset
发表于 2013-8-30 18:31:42
WaitX(dtime) , dtime 必须小于255.
smset
发表于 2013-8-30 18:32:37
本帖最后由 smset 于 2013-8-30 18:37 编辑
--------------------------------------------------------------------
unsigned chartask1(){
_SS
while(1){
WaitX(250);
WaitX(250);
while(TIMEOUT); //这是某个应用操作的超时等待;
RevBit(LED1_PORT, LED1_PIN);
}
_EE
}
再试试看
------------------------------------------------------------------
另外,我很不建议你这里 while(TIMEOUT);
因为这个调度器不建议在任务里面死循环,不释放出去。如果所有任务都是协作式的,很可能这样做永远就在这里循环了。
--------------------------------------------------------------------
unsigned chartask1(){
_SS
while(1){
WaitX(250);
WaitX(250);
while(TIMEOUT){
WaitX(0);
}
RevBit(LED1_PORT, LED1_PIN);
}
_EE
}
------------------------------------------------------------------
你的逻辑,可以这样来做。
或者用信号量来实现,也是可以的。
bondxie3
发表于 2013-9-2 08:18:11
smset 发表于 2013-8-30 18:32 static/image/common/back.gif
--------------------------------------------------------------------
unsigned chartask1(){
_SS
while(TIMEOUT)
{
WaitX(0);
}
这种方式有问题.使用如下方式才行
do
{
WaitX(0);
}while( TIMEOUT );
可以把这种方式定义成一个宏:
#define WaitUntil(CondExpr,Cyc) \
do \
{ \
WaitX(Cyc); \
}while( !(CondExpr) )
guxingganyue
发表于 2013-9-15 17:55:16
我也来一层,有机会了再研究。
zishan
发表于 2013-9-16 08:47:07
个人觉得就是一个软timer,由于没有上下文切换导致"任务"不能while(),实时性很不强,实用性有待加强.
wswh2o
发表于 2013-10-12 11:38:33
vc6.0好像不支持case __LINE__这种用法~~,提示“case expression not constant”
smset
发表于 2013-10-12 12:39:59
wswh2o 发表于 2013-10-12 11:38 static/image/common/back.gif
vc6.0好像不支持case __LINE__这种用法~~,提示“case expression not constant”
支持的哦,你检查下是不是哪里设置有问题。
我以前就用过vc下编译protothread,可以参考这里:
http://www.amobbs.com/forum.php?mod=viewthread&tid=4077658&highlight=protothread
liujie14565
发表于 2013-10-15 23:13:54
smset 发表于 2013-10-12 12:39 static/image/common/back.gif
支持的哦,你检查下是不是哪里设置有问题。
我以前就用过vc下编译protothread,可以参考这里:
楼主 有3个问题请教下:
1. 有3个任务,Task0 1ms 执行一次Task13ms 执行一次Task310ms 执行一次 会重叠 怎么处理好一点,
2.有4个任务,都是10ms执行周期 例如 Task0执行一次后 10ms 后在执行Task0 10ms 执行一轮怎么处理好一点,
Elec_Ramble
发表于 2013-10-15 23:36:29
学习了…
来自:amoBBS 阿莫电子论坛 Windows Phone 7 客户端
mcuprogram
发表于 2013-10-17 21:34:29
smset 发表于 2012-12-21 11:57 static/image/common/back.gif
综合这几天的讨论,先更新一版,仅供评测用:主要改动有: 1) 增加了RunTaskA宏,让前面的任务有优先执行 ...
mark
jsntzxh
发表于 2013-10-18 11:27:41
顶……………………
zl_123
发表于 2013-10-23 21:39:13
mark
wujh
发表于 2013-10-24 00:00:08
翻了几页还是不懂,先mark
mvpgpz
发表于 2013-10-24 09:08:07
太好了 哈哈 收藏!
mathison
发表于 2013-10-25 12:10:18
本帖最后由 mathison 于 2013-10-25 12:11 编辑
谢谢 smset 大师 的分享
我正在尝试 将大师的调度器 改写一个已经量产的 电推剪的项目中
使用的 义隆 EM78P259 的ic
用了8年的汇编 尝试一下 C开发的痛苦和乐趣
如果改写后的代码能达到客户的要求会和大家分享代码
目前在补C语言关于c语言的书 smset大师有推荐吗 ?
smset
发表于 2013-10-25 13:10:38
mathison 发表于 2013-10-25 12:10 static/image/common/back.gif
谢谢 smset 大师 的分享
我正在尝试 将大师的调度器 改写一个已经量产的 电推剪的项目中
使用的 义隆 EM7 ...
大师不敢当,我本是屌丝一枚。
我以前学习C语言,看的是谭浩强的书。
smset
发表于 2013-10-25 13:24:35
liujie14565 发表于 2013-10-15 23:13 static/image/common/back.gif
楼主 有3个问题请教下:
1. 有3个任务,Task0 1ms 执行一次Task13ms 执行一次Task310ms 执行一次 ...
根据你的描述,总体上你还是在以定时器加状态机的思路在描述需求。
当然,也能用小小调度器任务机制来实现。只是不是真正多任务的思想。
如果你的任务是毫秒级的,那你应该把定时器中断周期减少到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个函数,
然后用一个任务函数来实现。
baal
发表于 2013-10-25 14:27:18
时间片,系统,MARK
worldsing
发表于 2013-10-25 21:36:43
smset 发表于 2013-8-30 18:32 static/image/common/back.gif
--------------------------------------------------------------------
unsigned chartask1(){
_SS
嗯,这是可以也得到解决
但是这代码展开后应该是一个很长的函数调用关系
而不是真正意义的任务上调度器,当然也能完成
多任务,调度器应该做到任务有独立的空间,不限制
任务的操作。任务与任务独立,任务调度器隔离。
mathison
发表于 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:
}
}
}
mathison
发表于 2013-10-26 16:53:07
本人C开发新手
义隆的C编译器用起来真痛苦
有用C做义隆单片机开发的朋友吗 请问你们用什么编译器
追寻cheney
发表于 2013-10-26 19:14:50
下载学习,感谢楼主!!{:lol:}
jetli
发表于 2013-10-26 19:44:08
不明觉厉! 啊{:victory:}{:lol:}
zzz123456
发表于 2013-10-27 01:15:18
116 209 257 330 397 492 540 楼,楼主建议用492版。记号。
smset
发表于 2013-10-27 11:15:03
mathison 发表于 2013-10-26 16:41 static/image/common/back.gif
再次感谢 smset
附上我在 义隆单片机上的移植
芯片用的是 EM78P259N
不用谢,很支持你的做法!
因为小小调度器本来就是为小资源单片机而生的。
义隆单片机是很流行的小资源单片机,把小小调度器移植到这类单片机上去,并供他人借鉴参考,也是很有意义的。
liuqian
发表于 2013-10-28 10:59:54
从1楼一只看到最后,眼镜都麻了。我也是用时间那本书里面的框架,自己稍微改了改,发现LZ这个更实用。准备作个交通灯的项目,移植过去试试看,用freescale的8位机
tang0571
发表于 2013-10-28 11:15:57
好久不写程序了,还是要顶一下!
页:
1
2
3
4
5
6
[7]
8
9
10
11
12
13