[51单片机] 请教多任务系统的运行流程

[复制链接]
1367|10
 楼主| wdliming 发表于 2018-8-8 15:33 | 显示全部楼层 |阅读模式
网上有一个C51的多任务系统,但是对其代码的运行流程不太清楚,请各位网友大神们帮忙解释下。谢谢
  1. /*
  2. 使用keil4  ,代码Code Optimization:0   运行OK

  3. 可运行8个任务

  4. Program Size:
  5. data=21.0 xdata=0 code=401  (包括2个示例变量,未优化)

  6. 任务从中断处切换,在定时时间到后从定时中断中切换回来。

  7. 待改进地方

  8. 1.手动优化汇编程序

  9. 2. 重入问题

  10. 3.参数进函数和定时中断的保护问题

  11. */

  12. #include <regx52.H>
  13. #include <INTRINS.H>

  14. typedef unsigned char u8;
  15. typedef unsigned int u16;

  16. sbit LED1 = P2 ^ 0;
  17. sbit LED2 = P2 ^ 1;

  18. #define TIMER_RELOAD()  {TL0=0xf0;TH0=0xd8;}//使能T/C          初始10ms


  19. #define MAX_TASKS 2 //任务槽最大个数.
  20. u8 idata task_stack[MAX_TASKS][2];//任务堆栈.  PC指针为16位,需2个字节task_stack[][0]L  task_stack[][1]H。
  21. u8 idata task_time[MAX_TASKS]; //定时时间
  22. u8 task_id=0; //当前活动任务号
  23. u8 a=0;
  24. u8 b=0;

  25. void rtos_wait(u8 time)
  26. {
  27.     static u8 i;
  28.         //保存当前任务时间
  29.     task_time[task_id]=time;
  30.         //保存当前断点 并把SP=SP-2,任务切换到下一任务;
  31.     task_stack[task_id][1] =*((u8 data* )(SP));
  32.     SP--;
  33.     task_stack[task_id][0] =*((u8 data*)(SP));
  34.     SP--;

  35.     /* //任务号
  36.     if(++task_id == MAX_TASKS)
  37.     task_id = 0;
  38.      */
  39.                  
  40.         //任务号设为最大,越过最大则回到0
  41.     for(i=0; i<MAX_TASKS; i++)
  42.     {
  43.         if(task_time[i]==0)//根据定时时间判断
  44.         {
  45.             task_id=i;
  46.             break;
  47.         }
  48.     }
  49.         // if(i==MAX_TASKS) //任务满 超出则回到0
  50.         // {
  51.         // task_id=0;
  52.         // }

  53. }

  54. void task_test()
  55. {
  56.     while(1)
  57.     {
  58.         a++;
  59.                 LED2 = ~LED2;
  60.         rtos_wait(100); //执行完后,记录下一步地址,返回
  61.         a++;
  62.     }
  63. }
  64. void task_test2()
  65. {
  66.     while(1)
  67.     {
  68.         b++;
  69.                 LED1 = ~LED1;
  70.         rtos_wait(50); //执行完后,记录下一步地址,返回
  71.         b++;
  72.     }
  73. }
  74. void Timer0Init() //@18.432MHz
  75. {
  76.         TMOD &= 0xF0;                //设置定时器模式
  77.     TMOD |= 0x01;                //设置定时器模式   16bit timer
  78.     TL0 = 0xF0;                        //设置定时初值
  79.     TH0 = 0xD8;                        //设置定时初值 10ms
  80.     TF0 = 0;                        //清除TF0标志
  81.     TR0 = 1;                        //定时器0开始计时

  82.     ET0 = 1;                        //允许定时器0中断
  83.     EA = 1;                                 //开启总中断
  84. }
  85. void main()
  86. {
  87.     Timer0Init();
  88.     task_test();
  89.     task_test2();
  90.     while(1);
  91. }
  92. void task_sw() //任务时间是否到,任务时间到 实时切换回
  93. {
  94.         //从把定时时间减1 ,找看哪个任务到,任务时间到,则实时切换回
  95.     static u8 i;
  96.     for(i=0; i<MAX_TASKS; i++)
  97.     {
  98.         if(task_time[i])
  99.         {
  100.             task_time[i]--;
  101.             if(task_time[i]==0)//多个定时时间同时到,任务越靠后,越优先执行。
  102.             {
  103.                 task_id=i; //当前任务号
  104.                                 //保存的PC指针调出来
  105.                 SP++;
  106.                 (*((u8 data*)(SP)))=task_stack[i][0];
  107.                 SP++;
  108.                 (*((u8 data*)(SP)))=task_stack[i][1] ;
  109.             }
  110.         }
  111.     }
  112. }
  113. void tm0_isr() interrupt 1 //using 1
  114. {
  115.     //定时时间重载
  116.     TIMER_RELOAD();

  117.            //every 10ms to scan
  118.     task_sw(); //任务时间是否到,任务时间到 实时切换回
  119. }
任务加载后,是怎么做到任务切换的,main函数中的while(1);不会一直占用cpu吗??
mcu5i51 发表于 2018-8-8 15:45 | 显示全部楼层
大概看了一下,应是协作式的,任务中主动放权;
main中的死循环是一直用CPU,不过还有定时中断;
在任务中调用rtos_wait(50);时保存这个位置和中间数据,对参数中的时间倒计时,为0时恢复数据,运行rtos_wait(50);之后的指令;
相比常见的OS没有任务创建删除之类的,简单,用于有固定任务的情况
 楼主| wdliming 发表于 2018-8-8 16:05 | 显示全部楼层
mcu5i51 发表于 2018-8-8 15:45
大概看了一下,应是协作式的,任务中主动放权;
main中的死循环是一直用CPU,不过还有定时中断;
在任务中 ...

我想请问,他是怎么切换回去的,中断中能切换回去吗??
 楼主| wdliming 发表于 2018-8-8 16:06 | 显示全部楼层
mcu5i51 发表于 2018-8-8 15:45
大概看了一下,应是协作式的,任务中主动放权;
main中的死循环是一直用CPU,不过还有定时中断;
在任务中 ...

//任务号设为最大,越过最大则回到0
    for(i=0; i<MAX_TASKS; i++)
    {
        if(task_time==0)//根据定时时间判断
        {
            task_id=i;
            break;
        }
    }

这段代码是用于切换的吗?
mcu5i51 发表于 2018-8-8 16:13 | 显示全部楼层
wdliming 发表于 2018-8-8 16:06
//任务号设为最大,越过最大则回到0
    for(i=0; i

这是加入任务的
 楼主| wdliming 发表于 2018-8-8 16:20 | 显示全部楼层
mcu5i51 发表于 2018-8-8 16:13
这是加入任务的

定时时间不到,就保持原来的任务运行是吗?
mcu5i51 发表于 2018-8-8 16:23 | 显示全部楼层
你调试一下,可以比较清晰的理解;我只是大概看下,错处海涵。

评论

谢谢!!  发表于 2018-8-8 17:53
 楼主| wdliming 发表于 2018-8-8 16:43 | 显示全部楼层
mcu5i51 发表于 2018-8-8 16:23
你调试一下,可以比较清晰的理解;我只是大概看下,错处海涵。

好的,我把等待时间缩小调试下。。
ayb_ice 发表于 2018-8-8 16:44 | 显示全部楼层
只保存了任务的断点,意义不大吧
 楼主| wdliming 发表于 2018-8-8 16:45 | 显示全部楼层
ayb_ice 发表于 2018-8-8 16:44
只保存了任务的断点,意义不大吧

是网上找来的一个代码,在学习中。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:我的未来不是梦

76

主题

914

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部