kanfor 发表于 2008-9-10 18:39:57

看了这才发现之前好多问题没有注意到!

snn_snn 发表于 2008-9-10 23:52:03

有深度

wumei 发表于 2008-9-17 17:27:32

值得学习!

banyan_city 发表于 2008-9-17 17:55:55

学习了,

afctl 发表于 2008-9-17 18:38:06

记号一个

microyao 发表于 2008-9-18 01:36:54

引用顶楼



————————————————————————-————————

//任务装入函数

void task_load(unsigned int fn, unsigned char tid){

        task_sp = task_stack + 1;

        task_stack = (unsigned int)fn & 0xff;

        task_stack = (unsigned int)fn>> 8;

}

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



 在这几句中,第二行右边所得到的是一个地址数据,但这个地址是task_stack这个二维数组的第tid行的第一列的元素的地址。这个地址加载到task_sp中有什么用呢?是我理解错了?得到第tid行第一列的数据是不是应为*(task_sp+1)

如果没有理解错,那楼主的这个小系统就有点问题了。。。

这个地址似乎不是一个有用的数据。



请楼主为菜鸟解答。。。在线等。

本贴被 microyao 编辑过,最后修改时间:2008-09-18,01:42:38.

rainyss 发表于 2008-9-18 06:41:32

如果有问题还能工作得起来?这可是堆栈,错一丁点都不行的.





本贴被 rainyss 编辑过,最后修改时间:2008-09-18,06:43:18.

rainyss 发表于 2008-9-18 06:49:27

//任务装入函数 

void task_load(unsigned int fn, unsigned char tid){ 

        task_sp = task_stack + 1; //装入栈指针,该值在切换任务时会加载到SP中



        task_stack = (unsigned int)fn & 0xff; //向私栈中装入任务地址低8位

        task_stack = (unsigned int)fn>> 8; //任务地址高8位

} 



任务切换过程:



call task_switch函数

将SP值保存到task_sp中

将tid切换到下一个任务

将task_sp中的值装入SP中

ret from task_switch

eng5025 发表于 2008-9-18 08:33:01

http://www.ourdev.cn/bbs/emotion/em078.gif

出来一个多月了,现在才发现

microyao 发表于 2008-9-18 08:52:38

看来我得实验一下。怎么老感到与我脑中的标准C有冲突。。。

rainyss 发表于 2008-9-18 09:03:12

这几句里头没有用到非标准C的句型.

microyao 发表于 2008-9-18 09:05:07

实验证明。我是错的。。。



并己经明白了。谢谢楼主。好长时间没用汇编,要好好复习一下了。。。

本贴被 microyao 编辑过,最后修改时间:2008-09-18,09:12:07.

flyunlimit 发表于 2008-9-18 10:35:21

留名,要细看

hezhaofei 发表于 2008-9-19 18:15:57

好长的资料。 顶了慢慢看

zsy_zsy 发表于 2008-9-19 21:29:35

MARKING

jjj206 发表于 2008-9-21 11:58:47

好帖!收藏!

本贴被 jjj206 编辑过,最后修改时间:2008-09-21,12:00:11.

cyq001 发表于 2008-9-25 19:17:36

向楼主学习!

youlingfeng11 发表于 2008-9-26 23:42:34

为每个任务定义一字节计数器: 

unsigned char idata task_sleep;//任务睡眠定时器 



该计数器会在每次定时器中断时减1(除非它的值为0,或为0xff) 

void clock_timer(void) interrupt 1 using 1 

{ 



... 

        //任务延迟处理 

        i = MAX_TASKS; 

        p = task_sleep;  

        do{ 

                if(*p != 0 && *p != -1)//不为0,也不为0xff,则将任务延时值减1.为0xff表示任务已挂起,不由定时器唤醒 

                        (*p)--; 

                p++; 

        }while(--i); 

} 



相关宏: 

task_sleep(timer) 延时timer个定时器中断周期.取值0~254



楼主能否对计数器延时分析下吗,我怎么感觉你所写的计数器延时程序,为每个任务的延时是一样的,并且同时进行,每个中断周期同时轮次减1,这样延时准确吗

rainyss 发表于 2008-9-26 23:49:04

初值不同.减到零不再减,同时任务恢复正常调度

tianxingjian 发表于 2008-10-5 20:37:25

支持,楼主辛苦了

xjhhjx 发表于 2008-10-11 16:36:30

看来我现在才刚接触单片机看这个,有些头晕!

cookie2g 发表于 2008-10-11 17:47:14

记号

ym_avr 发表于 2008-10-12 11:02:40

不错!

dszx 发表于 2008-10-12 22:34:54

不错,好东西!

sol84 发表于 2008-10-13 08:46:18

好贴,学习了

cyberkt 发表于 2008-10-13 09:17:24

好贴,mark

xiangyuan_122 发表于 2008-10-13 12:22:51

顶 慢慢看 好东西

jerrymissy 发表于 2008-10-13 14:31:04

怎么好的东西

不能不说酷~

严重支持~

fandebin 发表于 2008-10-13 14:59:06

确实是好贴啊,现在正在学rtx51,看完之后收获良多啊,有没有专门研究51嵌入式系统的群啊,要是有的话,加我,250733345,要是没有的话,我可以建一个,希望大家顶一下

aitchouyz 发表于 2008-10-13 16:31:03

关注

draapho 发表于 2008-10-13 16:45:54

原来协作式“操作系统”没人说?曾今这个论坛似乎有人对“协作式”很不屑的。。。

其实8位单片机由于受ram限制,很合适协作式,根本不合适用 抢占式。

而用了“操作系统”的好处当然是思路清晰明了,编程方便。



既然这样,我发个自己在用的一个 协作式..... 标准C写的。不管51或AVR都能用的





/* ======================  I N C L U D E   F I L E  ========================= */

#include  "EZSYS_KERNEL.h"



/* ======================  M A C R O   D E F I N E  ========================= */

#if ((SYSTEM_TASK_NUM == 0) || (SYSTEM_TASK_NUM> 256))         // 这个是系统任务数判断,在h文件中宏定义一下就OK了

  #error "SYSTEM_TASK_NUM error!!!"

#endif



/* ======================  G L O B A L E   V A R I A B L E  ================= */



/* ======================  S T A T I C   G L O B A L E   V A R I A B L E  === */

static struct _ezsys_task_struct                          // 任务数*4 就是该 协作式....要掉的ram

{

  void (*taskPtr)(void);                                                        // 函数指针

  U16  delayTimer;                                                              // 延时服务用

}

ezSys[ SYSTEM_TASK_NUM ];



/* ======================  S T A T I C   F U N C T I O N  =================== */







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

 * Function Name    : SIGNAL(SYSTEM_TIMER_VECTOR)

 * Description      : 系统定时周期中断函数

 *

 * Input  Parameter : No Parameter.

 * Output Parameter : No Parameter.

 * Global Parameter : No Parameter.

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

SIGNAL(SYSTEM_TIMER_VECTOR)            // 系统定时周期,主要用来计数delayTimer的,顺便给了个定时服务函数

{ 

  U08 i;



  ReloadSystemTimerCounter();                                                   // 重新载入定时器值



  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    if (ezSys.delayTimer) ezSys.delayTimer--;

  }



  SystemTimerServe();                                                           // 系统定时周期服务函数

}



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

 * Function Name    : main()

 * Description      : 主函数

 *

 * Input  Parameter : No Parameter.

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System 的全局变量。

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

void main(void)

{

  U08 i;



  CLI();

  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    ezSys.taskPtr = 0;

    ezSys.delayTimer = 0;

  }

  SystemInitServe();                                                            // 初始化服务函数

  WatchDogEnable();                                                             // 使能看门狗



  while(1)                                                                      // 系统调度

  {

    for (i=0; i < SYSTEM_TASK_NUM; i++)      // 有人说这就是个超循环,前后台的任务,怎么能称为操作系统?

                                             // 答对了,这就是个超循环调度。是不是操作系统我无所谓,不就个名称么,

                                             // 用着方便合适就好了,在嵌入式世界,只有最合适的,没有最好的!!!!

    {

      CLI();

      if ((ezSys.taskPtr !=0 ) && (ezSys.delayTimer == 0))  // 这一版本没有增加优先级,不符合执行条件的直接下一任务

      {

        SEI();

        ezSys.taskPtr();                                                     // 延时时间到,运行任务

      }

      SEI();

    }

  }

}



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

 * Function Name    : TaskAdd()

 * Description      : 添加一个系统任务

 *

 * Input  Parameter : funPtr    -- 要创建的函数。

 *                    delayTime -- 任务延时运行的时间。

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System的全局变量。

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

void TaskAdd(void (*funPtr)(void), U16 delayTime)

{

  U08 i;



  for (i=0; i < SYSTEM_TASK_NUM; i++)                                           // 检查任务是否已存在

  {

    if (ezSys.taskPtr == funPtr)

    {

      Assert("TaskExist");

      return;

    }

  }



  for (i=0; i < SYSTEM_TASK_NUM; i++)                                           // 添加任务

  {

    if (ezSys.taskPtr == 0)

    {

      CLI();

      ezSys.taskPtr = funPtr;

      ezSys.delayTimer = delayTime;

      SEI();

      return;

    }

  }



  Assert("TaskFull");

}



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

 * Function Name    : TaskDel()

 * Description      : 删除一个系统任务.

 *

 * Input  Parameter : funPtr -- 要删除的函数。

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System的全局变量。

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

void TaskDel(void (*funPtr)(void))

{

  U08 i;



  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    if (ezSys.taskPtr == funPtr)

    {

      CLI();

      ezSys.taskPtr = 0;

      ezSys.delayTimer = 0;

      SEI();

      return;

    }

  }

}



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

 * Function Name    : TaskDelay()

 * Description      : 延时运行一个任务.

 *

 * Input  Parameter : funPtr    -- 要延时运行的函数。

 *                    delayTime -- 任务延时运行的时间。

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System的全局变量。

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

void TaskDelay(void (*funPtr)(void), U16 delayTime)

{

  U08 i;



  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    if (ezSys.taskPtr == funPtr)

    {

      CLI();

      ezSys.delayTimer = delayTime;

      SEI();

      return;

    }

  }

}







/* ======================  T H E   E N D  =================================== */

eiglxl 发表于 2008-10-13 16:48:48

谢谢,学习了。

heizi302 发表于 2008-10-18 01:15:42

学习中。。。。。。。。。。

nuno 发表于 2008-10-20 00:13:59

学习中............................

rainyss 发表于 2008-10-20 12:16:47

建了个群,4759163,专门用来讨论超轻量OS.

刚建好,目前里面没啥讨论,想加入的话,确认你是否有耐心等着人多起来吧.

chigaoyuan 发表于 2008-10-22 23:57:12

迷糊,好象无从下手

max232 发表于 2008-10-30 10:22:31

学习了

cowboy 发表于 2008-10-30 11:03:45

学习中.mark

zy851001 发表于 2008-10-30 12:54:19

顶起

tomy 发表于 2008-10-30 16:10:33

看了以上的,,有点晕了,,



感觉有点像那种分别复用的,



不知道高手们能不能解释下以上介绍的与分时复用的有什么区别?



劳烦了,,谢谢

学习了~~

rainyss 发表于 2008-10-30 21:56:53

就是分时复用啊.多任务OS,就是制定一种分时复用的规则

本贴被 rainyss 编辑过,最后修改时间:2008-10-30,22:25:56.

82587299 发表于 2008-10-31 09:43:03

顶一个

ym_avr 发表于 2008-10-31 11:23:21

mark!

xt0320 发表于 2008-10-31 13:36:00

楼主好像笔误少了这句:

unsigned char idata task_sp;//任务的栈指针

ales.l.j 发表于 2008-10-31 16:01:43

打上数码标记

tomy 发表于 2008-11-4 08:50:25

回【143楼】 rainyss



谢谢了,,那这样就更好看懂了!



顶起  

rainyss 发表于 2008-11-4 11:56:10

【146楼】 xt0320 

积分:6

派别:

等级:------

来自:

 楼主好像笔误少了这句: 

unsigned char idata task_sp;//任务的栈指针  







你看得可真够仔细的.厉害.估计大部分人都没有注意到.

kengao55 发表于 2008-11-4 12:21:12

收藏了啊

abs123 发表于 2008-11-4 12:22:35

真的不错,有空仔细看看,mark

mbj2003 发表于 2008-11-7 02:20:26

好贴,简单通俗易懂,是学习的好材料

armok 发表于 2008-11-7 03:12:54

【146楼】 xt0320 

积分:6

派别:

等级:------

来自:

 楼主好像笔误少了这句: 

unsigned char idata task_sp;//任务的栈指针  





佩服啊!

rainyss 发表于 2008-11-9 00:31:28

【152楼】 gamethink 

积分:1023

派别:

等级:------

来自:

 void task_switch(){ 



        task_sp = SP; 



        if(++task_id == MAX_TASKS) 

                task_id = 0; 



        SP = task_sp; 

} 



怎么觉得task_sp = SP;是完全没有作用的...调试了很多次也没发现具体作用  









你把它删了试试看.

robinyuan 发表于 2008-11-9 01:07:08

这个RTOS的主要问题就是要限制子程序里的代码不要太长,以防止实时性不够

但一般LCD的显示程序比较长,有无好方法处理

D138138 发表于 2008-11-9 15:32:09

不错,在操作系统下写程序,就是要先把操作系统的思路搞明白了。

rainyss 发表于 2008-11-9 22:55:08

【156楼】 robinyuan 



积分:130

派别:

等级:------

来自:

 这个RTOS的主要问题就是要限制子程序里的代码不要太长,以防止实时性不够 

但一般LCD的显示程序比较长,有无好方法处理  







找几个点插入若干task_switch()就行了.

xaofen 发表于 2008-11-10 15:26:22

收藏先,,

llych 发表于 2008-11-10 17:51:04

到这里 就看到了这个好贴子  学习了

helloavr 发表于 2008-11-10 19:13:04

mark

xihacow 发表于 2008-11-11 22:01:19

好贴,多谢分享

lk546 发表于 2008-11-23 00:04:20

学习,多谢!

gliet_su 发表于 2008-11-23 01:35:14

8位机就不用搞操作系统了,

不过要有操作系统的思想。

zhaolong123 发表于 2008-11-29 11:33:36

好贴,学习中~~~~

moan 发表于 2008-11-29 11:54:21

mark

superyongzhe 发表于 2008-11-29 11:54:43

很好的学习资料

sbsdys 发表于 2008-12-1 21:15:20

mark!

jackybany 发表于 2008-12-1 23:17:58

好!好,好!!非常好!!!

rainyss 发表于 2008-12-2 00:38:27

【171楼】 gamethink 



积分:1057

派别:

等级:------

来自:广州

 LZ,其实一直不太明白"监听进程"的具体意思和作用. 

按我理解,是不是看看另外一个任务是否有被挂起???  

   





得看上下文.有两种可能:

一种是用于监控其它进程的进程,但这种可能性小,"监听"二字用得不规范,应该叫"监控".

"监听进程"通常指的是等待外部触发条件发生的进程.比如等待网络包到达,等待串口数据到达,等待引脚电平翻转.



"监听"二字必定"服务"及"事件"挂勾.每种监听都对应着相应的事务处理.当事件发生时,监听被激活,转入或开启新进程进入事件处理的服务流程,处理完成后回到等待状态.等待过程中监听进程就像一个老式电话局里等待客户请求接线的接线生,所以叫"监听".

本贴被 rainyss 编辑过,最后修改时间:2008-12-02,00:43:47.

zhameng 发表于 2008-12-2 08:00:51

太好了!谢谢!

学习中~~~~

rainyss 发表于 2008-12-4 11:31:42

比较接近了.监听就意味着挂起.

操作系统里有"事件"和"锁"的概念.

当事件未发生时,监听进程读取共享锁被挂起.当底层程序(例如中断)发现指定的动作发生时,比如串口数据到达时,底层程序会将数据以事件(有时也叫消息或邮件)的形式唤醒监听进程.



在我写的例子中没有使用锁,而是用了挂起功能.消息是用唤醒功能完全的.当然,了解了原理则区别不大.

michaelc21 发表于 2008-12-9 13:37:07

谢谢楼主。



对 了解 操作系统 很有帮助。





本贴被 michaelc21 编辑过,最后修改时间:2008-12-09,18:07:45.

fuliaokai 发表于 2008-12-9 13:49:58

顶一个

kejian2000 发表于 2008-12-10 16:10:52

to gamethink:



当task1内调用一个子程序sub1,而sub1内又调用了task_switch时

下面这句就不能删除了:

task_sp = SP; 





此时,sub1分享task1的task_id

我写了个小程序已经验证过了



#include <reg52.h>  



#define MAX_TASKS 2       //任务槽个数.必须和实际任务数一至  

#define MAX_TASK_DEP 12   //最大栈深.最低不得少于2个,保守值为12.  

unsigned char task_id;    //当前活动任务号

unsigned char task_sp;  

unsigned char idata task_stack;//任务堆栈.  





//任务切换函数(任务调度器)  

void task_switch(){  

        task_sp = SP;  



        if(++task_id == MAX_TASKS)  

                task_id = 0;  



        SP = task_sp;  

}  



//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任务,则原任务丢失,但系统本身不会发生错误.  

void task_load(unsigned int fn, unsigned char tid){  

        task_sp = task_stack + 1;  

        task_stack = (unsigned int)fn & 0xff;  

        task_stack = (unsigned int)fn>> 8;  

}  



//从指定的任务开始运行任务调度.调用该宏后,将永不返回.  

#define os_start(tid) {task_id = tid,SP = task_sp;return;}  







//////////////////////////////////////////////////////////////////////////

void sub1()

{

        unsigned char a,b;

        a++;

        task_switch();

        b++;

}



//////////////////////////////////////////////////////////////////////////



/*============================以下为测试代码============================*/  



void task1(){  

        static unsigned char x,y,z;  

        while(1){  

                x++;  

                task_switch();//编译后在这里打上断点  

                y++; 

             sub1(); 

                task_switch();//编译后在这里打上断点  

                z++;  

                task_switch();//编译后在这里打上断点  

        }  

}  



void task2(){  

        static unsigned char l,m,n;  

        while(1){  

                l+=2;  

                task_switch();//编译后在这里打上断点  

                m+=2;  

                task_switch();//编译后在这里打上断点  

                n+=2;  

                task_switch();//编译后在这里打上断点  

        }  

}  



void main(){  

        //这里装载了两个任务,因此在定义MAX_TASKS时也必须定义为2  

                task_load(task1, 0);//将task1函数装入0号槽  

        task_load(task2, 1);//将task2函数装入1号槽  

        os_start(0);  

}  



本贴被 kejian2000 编辑过,最后修改时间:2008-12-10,16:11:54.

ddcour 发表于 2008-12-10 22:56:26

留着!

czhaii 发表于 2008-12-11 09:57:35

顶一下,没想过51搞系统

mike_K 发表于 2008-12-17 09:13:52

做个记号

w418781840 发表于 2008-12-18 19:52:29

不顶不行

stoneee 发表于 2008-12-18 23:24:20

确实强悍。

rainyss 发表于 2008-12-19 05:40:53

【186楼】 gamethink 



积分:1093

派别:

等级:------

来自:广州

 to kejian2000  

谢谢你的回答,我试过确实不能够删除 



to LZ 

我从"3.消息机制"开始就看得很迷惑了...其实是不是还有其它文章没放的?而且和源代码的差别也很大  

   









消息机制是一种软件机制,用于进程间通信的.就是说,你要理解消息,就要先真正理解什么叫进程,为什么要进行进程间通信,进程间通信通的是什么东西.接下来要理解进程挂起和唤醒.这些背景知识不先理解,则无法理解消息的含义.

限于篇幅我并没有解释这些东西,因为帖子的主要目的是"如果搭一个精简的操作系统"而非"操作系统原理教学",写太啰嗦反而搞得谁都看不下去.

本贴被 rainyss 编辑过,最后修改时间:2008-12-19,05:45:48.

footballboy9 发表于 2008-12-24 16:21:38

   高人!佩服

zcllom 发表于 2008-12-24 16:39:19

这个帖子应该带 两个 酷 字,因为比一般的 酷 贴 要精致的多。

swordKING 发表于 2008-12-25 15:05:36

看过留名,回来就实现一下多任务系统!

zcllom 发表于 2008-12-25 15:32:05

能够把这种思想在PIC单片机上实现吗?PIC单片机的堆栈不可访问啊。

本贴被 zcllom 编辑过,最后修改时间:2008-12-25,16:07:20.

rainyss 发表于 2008-12-27 02:43:39

to192楼



那些背景知识要系统全面的讲会很复杂,不全面讲又会引出更多的疑问,反而搞得晕头转向.个人认为这些知识还是先找本操作系统原理的书看看比较好.



操作系统里绝大部分概念都是鸡与蛋的关系,必须使用反复通读慢慢了解全盘渐近的方法,才能真正吸收,靠背,靠教,作用都不大

Canbus007 发表于 2008-12-27 16:00:15

置顶!!

向楼主(rainyss)学习了。!

偶滴QQ:278081591

rainyss 发表于 2009-1-2 17:59:35

<<操作系统原理>>是一定要看的,不用精读,以大至看懂概念为标准通读一遍,不懂的先记下来,在读完第一遍后重读,如此迭低若干次.



接下来去google里搜"实时多任务",将两方面的知识结合起来.



做完这两部分后去找陈明计和电脑圈圈,这两人的OS模型一个倾向于"正规化作战"一个喜欢搞"游击战".吸收他们的个性到你的知识体系中去.记住,知识本身位居其二,个性才是知识的本源.



说起来简单做起来并不易,要持之以恒长期努力,且永远不要认为自已已经懂了.

a105 发表于 2009-1-2 19:06:36

学习!

XUEPENGBIN 发表于 2009-1-2 19:40:34

shi kuai hao zhuan a

ssrc 发表于 2009-1-4 10:18:36

厉害!

guojielong777 发表于 2009-1-4 10:48:09

mark

guojielong777 发表于 2009-1-4 10:48:11

mark

wtliu 发表于 2009-1-4 14:06:36

众位都很牛!呵呵!

h85968099 发表于 2009-1-9 19:41:05

不平凡啊

neohp 发表于 2009-1-12 23:45:17

牛年更牛啊

fzpxp 发表于 2009-1-20 15:32:41

我顶!!!

nicksean 发表于 2009-1-23 22:20:24

学习!

patrickwong 发表于 2009-1-24 14:29:34

楼主好.



我把你的 mtask 项目移植到一块测试目标板上跑. 是驱动一块12864的LCD的. 开始一会就跑飞了. 



原本测试的代码是没问题的:





#include "glcd.h"

#include "8051.img"

#include "welcome.img"



#define DELAY 10000



void main(void)

{

idata unsigned int i;

unsigned char array = {"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()[]{}|\\<>?/|\0"};

unsigned short c;



  GLCD_LcdInit();



  while(1)

  {

    for(i = 0; i < 10; i++)

    {

      GLCD_ClearScreen();

      GLCD_Locate(0, 0);

      LcdPutchar(array, &Font_System3x6);

      LcdDelay(DELAY);



      GLCD_ClearScreen();

      GLCD_DisplayPicture(image2);

      LcdDelay(DELAY);



      GLCD_ClearScreen();

      GLCD_DisplayPicture(image3);

      LcdDelay(DELAY);



      /* software delay time */

      c = 3000;

      while (c--);

    }

  }  

}





把三段显示的代码套进任务内就出现问题了:



void task1(void)

{

static unsigned char i;



  i = 0;



  while(1)

  {

    stra = strb;



    if(++i == sizeof(stra))

      i = 0;



    GLCD_ClearScreen();

    GLCD_Locate(0, 0);

    LcdPutchar(array, &Font_System3x6);

    LcdDelay(DELAY);



    task_switch();

  }

}



void task2(void)

{

static unsigned char i;

  i = 0;



  while(1)

  {

    stra = strb;



    if(++i == sizeof(stra))

      i = 0;



    GLCD_ClearScreen();

    GLCD_DisplayPicture(image2);

    LcdDelay(DELAY);



    task_switch();

  }

}



void task3(void)

{

unsigned char i;



  while(1)

  {

    i = sizeof(stra);



    GLCD_ClearScreen();

    GLCD_DisplayPicture(image3);

    LcdDelay(DELAY);



    do

    {

      stra = strb;

    } while(--i);



    task_switch();

  }

}



void main(void)

{

  GLCD_LcdInit();



  task_load(task1, 0);

  task_load(task2, 1);

  task_load(task3, 2);



  os_start(0);

}



显示的函数都在 task_switch() 前完成, 应不会有覆盖的问题吧?

rainyss 发表于 2009-1-24 15:19:41

不存在你担心的覆盖问题,跑飞跟函数没有关系.跑飞极有可能是你内存使用过量引起的



void main(void) 

{ 

idata unsigned int i;  //题外话,这个变量没必要定义为idata,idata太占CPU资源,好象也没有必要用uint吧?uchar够用了

unsigned char array = {"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()[]{}|\\<>?/|\0"};     //  这个数组应定义为unsigned char code array[] 

unsigned short c; 



最后,你的LcdDelay(DELAY)函数是不应该使用的,多任务操作中不应使用空循环,除非延时时间足够短,因为延时期间CPU是被白白消耗的.我另一个例子里有task_sleep()的实现方法,不占CPU资源,延时最小单位为1 tick,你可以参考一下.

本贴被 rainyss 编辑过,最后修改时间:2009-01-24,15:24:30.

lwang 发表于 2009-2-1 11:02:10

不错,留个记号

jarte 发表于 2009-2-1 11:10:39

mark

linshl 发表于 2009-2-1 21:51:47

牛人阿!!!

喜欢这个论坛的共享方式,谢谢楼主和论坛版主!!!
页: 1 [2] 3 4 5 6 7 8 9 10 11
查看完整版本: 给51 DIY超轻量级多任务操作系统