原理

最简单的 OS 就是合作式操作系统,实现的方式是循环检查任务可执行标志,这个标志会在时间中断中来设置。优点是简单不容易出bug,缺点是实时性一般,并且每个任务需要拆分很细,最好小于时间中断。

实现

OS头文件

os_cfg.h

#include "reg51.h"
#define TIME_PER_SEC 200    //定义任务时钟频率,200Hz
#define CLOCK 22118400    //定义时钟晶振,单位Hz
#define MAX_TASK 4      //定义任务数量
//函数变量声明,在需要用以下函数或变量的文件中包含此头文件即可
extern void task0(void);
extern void task1(void);
extern void task2(void);
extern void task3(void);
extern unsigned char task_delay[MAX_TASK];
extern void run(void (*ptask)());
extern void os_timer0_init(void);

OS 源文件

os_c.c

#include "os_cfg.h"
unsigned char task_delay[MAX_TASK];  //定义任务延时量变量
//定时器0初始化
void os_timer0_init(void)
{
      unsigned char i;
      for(i=0;i<MAX_TASK;i++) task_delay[i]=0;
      TMOD = (TMOD & 0XF0) | 0X01;    //定时器 0工作在模式 1,16Bit 定时器模式
      TH0 = 255-CLOCK/TIME_PER_SEC/12/256;
      //CRY_OSC,TIME_PER_SEC在 os_cfg.h中定义
      TL0 = 255-CLOCK/TIME_PER_SEC/12%256;
      TR0 =1;
      ET0 =1;         //开启定时器和中断
}

// 系统 OS定时中断服务
void os_timer0(void) interrupt 1
{
      unsigned char i;
      TH0 = 255-CLOCK/TIME_PER_SEC/12/256;
      TL0 = 255-CLOCK/TIME_PER_SEC/12%256;
      //每节拍对任务延时变量减1 ,减至 0  后,任务就绪。
      for(i=0;i<MAX_TASK;i++) if(task_delay[i]) task_delay[i]--;
}

//指向函数的指针函数
void run(void (*ptask)())
{
      (*ptask)();
}

使用代码

main.c

#include "os_cfg.h"
#define TASK_DELAY0 TIME_PER_SEC/1      //任务执行频度为1Hz
#define TASK_DELAY1 TIME_PER_SEC/2      //任务执行频度为2Hz
#define TASK_DELAY2 TIME_PER_SEC/10      //任务执行频度为10Hz
#define TASK_DELAY3 TIME_PER_SEC/20     //任务执行频度为20Hz

void (* code task[])() = {task0,task1,task2,task3};  //获得任务PC指针

sbit LED0 = P1^0;  //演示用 LED接口定义
sbit LED1 = P1^1;
sbit LED2 = P1^2;
sbit LED3 = P1^3;

/*main主函数*/
void main(void)
{
      unsigned char i;
      os_timer0_init();   //节拍发生器定时器初始化
      EA = 1;       //开总中断

      while(1)
      {
	      for(i=0;i<MAX_TASK;i++)
	      if (task_delay[i]==0) {run(task[i]); break;}  //就绪任务调度
	      //上一行 break有特殊作用,详细解释见后文
      }
}

void task0(void)  //任务 0
{
      LED0 = !LED0;
      task_delay[0] = TASK_DELAY0;
}

void task1(void)  //任务 1
{
      LED1 = !LED1;
      task_delay[1] = TASK_DELAY1;
}

void task2(void)  //任务 2
{
      LED2 = !LED2;
      task_delay[2] = TASK_DELAY2;
}

void task3(void)  //任务内分段设计
{
      static unsigned char state=0;  //定义静态局部变量
      switch (state)
      {
	      case 0:
		      LED3 = !LED3;
		      state = 1;
		      task_delay[3] = TASK_DELAY3;
		      break;

	      case 1:
		      LED3 = !LED3;
		      state = 2;
		      task_delay[3] = TASK_DELAY3*2;
		      break;

	      case 2:
		      LED3 = !LED3;
		      state = 0;
		      task_delay[3] = TASK_DELAY3*4;
		      break;

	      default:
		      state = 0;
		      task_delay[3] = TASK_DELAY3;
		      break;
      }
}