zoukankan      html  css  js  c++  java
  • μc/osⅡ简化版任务机制浅析

      去年玩过一阵单片机,也用过μc/osⅡ的系统,但是就理解内核而言,整个即时操作系统还是过于冗杂,很多的东西很不适合初学者来动手操作,多方查找我发现他的任务机制可以进行功能的进一步简化,

    可以类似于任务栈的方式,使用纯C写成而不用汇编代码,闲话少说上代码吧。

      我的github上有我的渣代码=_=:https://github.com/lfkdsk

      灵魂画作任务图: 

    随手就是灵魂画作=-=

      1.主函数:

     1 #include "OS_task.h"
     2 #include "89c51.h"
     3 #include "main.h"
     4 #include "task_switch.h"
     5 #include <reg52.h>
     6 sbit K1=P0^0;
     7 void del10ms()
     8 {
     9     unsigned char a,b,c;
    10     for (c=1;c>0;c--)
    11         for(b=0;b<38;b++)
    12            for(a=0;a<130;a++);
    13 }
    14 void task_1()
    15 {
    16     while(1)
    17     {
    18         if(K1==0)
    19             del10ms();
    20           if(K1==0)
    21             {
    22                 task_switch();    
    23             }
    24     }
    25 }
    26 
    27 void task_2()
    28 {
    29     while(1)
    30     {
    31         if(K1==0)
    32             del10ms();
    33           if(K1==0)
    34             {
    35                 task_switch();    
    36             }
    37     }
    38 }
    39 
    40 void task_3()
    41 {
    42 
    43     while(1)
    44     {
    45         if(K1==0)                              //这里是五个放在任务栈里的空函数,只用里一个循环来循环监听按键,可以再循环中加入自己的东西,比如亮起小灯啊,什么的易于观察的现象
    46             del10ms();
    47           if(K1==0)
    48             {
    49                 task_switch();    
    50             }
    51     }
    52 }
    53 
    54 void task_4()
    55 {
    56     while(1)
    57     {
    58         if(K1==0)
    59             del10ms();
    60           if(K1==0)
    61             {
    62                 task_switch();    
    63             }
    64     }
    65 }
    66 
    67 void task_5()
    68 {
    69     while(1)
    70     {
    71         if(K1==0)
    72             del10ms();
    73           if(K1==0)
    74             {
    75                 task_switch();    
    76             }
    77     }
    78 }
    79 void main(void)
    80 {
    81 //    载入函数 优先级 任务名 任务ID
    82     task_load(2,task_1, 0);
    83     task_load(3,task_2, 1);
    84     task_load(4,task_3, 2);
    85     task_load(5,task_4, 3);
    86     task_load(6,task_4, 4);
    87     OS_Start(0);
    88 }

    2.任务装载(核心):

     1 #ifndef __OS_TASK_H__
     2 #define __OS_TASK_H__
     3 //任务功能
     4     //最大任务数
     5 #define MAX_TASK 5
     6     //堆栈深度
     7 #define SRACK_DEPTH 20
     8     //保存切换任务时软件压栈字节数
     9 #define Num_PUSH_bytes 13
    10     //程序控制块结构
    11 typedef struct 
    12 {
    13      unsigned char Task_SP;       //任务堆栈指针
    14      unsigned char Priority;      //优先级,值越小,优先级越高
    15 
    16 }PCB;
    17 
    18 extern idata volatile PCB OS_PCB[MAX_TASK];//定义堆栈
    19 extern volatile unsigned char OS_TASK_ID;//定义任务ID
    20 void task_load(unsigned char PRI,unsigned int FN,unsigned char T_ID);
    21 void OS_Start(T_ID);
    22 #endif
     1 //系统任务程序
     2 #include "OS_task.h"
     3 #include "89c51.h"
     4 #include "main.h"
     5 #include "task_switch.h"
     6 #include <reg52.h>
     7 //程序控制块
     8 idata volatile PCB OS_PBC[MAX_TASK];    //volatile是为了每次必须读值 这个是任务栈的最大任务数,任务栈名字叫PCB=-=
     9 
    10 //当前运行任务的ID号
    11 volatile unsigned char OS_TASK_ID;      
    12 
    13 //声明堆栈,由最大任务数和栈深定义的二维数组
    14 unsigned char idata OS_Stack[MAX_TASK][SRACK_DEPTH];    
    15 
    16 //任务装载函数
    17 void task_load(unsigned char PRI,unsigned int FN,unsigned char T_ID)
    18 {
    19     OS_PCB[T_ID].Priority=PRI;            //因为是简化的,所以我手动设置了优先级
    20     OS_PCB[T_ID].Task_SP=OS_Stack[T_ID]+1;     //这里取出了当前正在运行的任务的函数地址的高八位存为指针
    21     OS_Stack[T_ID][0] = (unsigned int)FN & 0xff;  //低八位存0
    22     OS_Stack[T_ID][1] = (unsigned int)FN << 8;   //高八位存在1里
    23 }
    24 
    25 //任务运行函数
    26 void OS_Start(T_ID)
    27 {
    28     OS_TASK_ID=T_ID;
    29     SP=OS_PCB[OS_TASK_ID].Task_SP;        //传入一个id,然后把sp指针指向它,sp指针是系统的任务指针,用于指向执行任务的
    30                      //之后就不管了,就会按照自己的方式运行了
    31 }

    3.任务切换:

     1 //任务交换程序
     2 #include "OS_task.h"
     3 #include "89c51.h"
     4 #include "main.h"
     5 #include "task_switch.h"
     6 #include <reg52.h>
     7 //任务调度函数
     8 void task_switch(){
     9     static int i;
    10     unsigned char j,MAX; 
    11     OS_PCB[OS_TASK_ID].Task_SP = SP;       //先把运行的指针地址存到该任务id对应的指针空间中
    12     for(i=0;i<MAX_TASK;i++)
    13     {
    14         MAX=j;                    //然后在循环找到优先级最高的(Priority最小的
    15 if(OS_PCB[j].Priority<OS_PCB[i].Priority||j!=OS_TASK_ID) //如果优先级高,则切换之
    16 {
    17     j=i;
    18     }
    19 }
    20     OS_TASK_ID=j;
    21     SP = OS_PCB[OS_TASK_ID].Task_SP;
    22 }

    好了,到这我们的精简版任务机制就搞定了,大家可以去试试啦,利用类堆栈的存储函数运行地址的方式进行挂起操作,来循环运行任务

    么么哒,求赞=_=

  • 相关阅读:
    Skyline软件SFS服务介绍
    选择三维地理信息系统(GIS)软件平台需要考虑的内容
    如何利用Skyline6.1的接口创建动态对象DynamicObject
    Skyline中的隐藏组
    基于Skyline的TerraExplorer6.1.1如何通过二次开发实现折线和多边形对象的手动绘制
    如何利用Skyline6.1实现多球对比功能
    Skyline for Android & iOS devices
    VBS、WKT、投影
    FME+Oracle Spatial+SFS+TEPro
    如何生成静态页
  • 原文地址:https://www.cnblogs.com/lfk-dsk/p/4442104.html
Copyright © 2011-2022 走看看