51单片机基于时间片轮转的简单rtos

早就想写写这个了,正好赶上有点时间,写了一下基于51单片机的时间片轮转调度系统,简单的rtos,呵呵。直接上代码。

cpp 复制代码
//基于51单片机时间片轮转的简单rtos。
#include"reg52.h"
sbit led1 = P2^7;
sbit led2 = P2^0;
sbit key = P1^0;
#define MAX_TASKS     3       //定义任务个数.必须和实际任务数一至 
#define PUSH_TIMES    3 	  //时间中断中push使用的次数用debug看进入时间中断时的次数。
#define MAX_TASK_DEP  (PUSH_TIMES+4)  //任务槽深度;
//经过实验,看debug的push次数,加上4就行了。//没有考虑中断嵌套。有嵌套的再大。
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];      //任务堆栈.
unsigned char current_id;         //当前活动任务号 
unsigned char task_sp[MAX_TASKS];	//堆栈指针组,每个任务一个字节,任务调度前指向入栈的pc高字节。
unsigned int cicle1,cicle2;
void Timer0_Init(void)		//10毫秒@11.0592MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x00;				//设置定时初始值
	TH0 = 0xDC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0 = 1;				//使能定时器0中断
	EA=1;					//开总中断
}

//任务装入函数,将任务的首地址(参数1)装入(参数2)指定的任务槽中.
void task_load(unsigned int func, unsigned char taskid)
{ 
        
        task_stack[taskid][0] = (unsigned int)func & 0xff;  //把任务地址的低八位装入任务槽0号地址。
        task_stack[taskid][1] = (unsigned int)func >> 8;    //把任务地址的高八位装入任务槽1号地址
        task_sp[taskid] = (unsigned char)&task_stack[taskid][0]; //把堆栈的首地址送给sp数组。
        task_sp[taskid]++;//先把保存的数组sp值加1,使它指向堆栈入栈pc的高位
//这里模拟了入栈过程,先把任务地址放在任务槽的最低位置,下次切换的时候就直接来这里找。
		   
		if(taskid!=0)									   //如果不是0号任务;
		{
		task_sp[taskid]+= PUSH_TIMES;					   //给push和pop语句留下空间,用debuge看汇编进入中断后的push
		                                               //次数,在文件首部改数字值;
		}
} 

void  os_start() 	 //启动程序
 {
 current_id = 0;	 //把0号sp当作当前的首个sp
 SP = task_sp[0];

 } 
void task1()	//任务1,循环够5万次灯闪动一次
{ 
        while(1)
		{ 
			cicle1++;
				 if (cicle1>50000)
				 {
				  cicle1=0;
				  led1=!led1;
				 }
        } 
} 
void task2()  	//任务2,循环够5万次灯闪动一次
{ 
        while(1)
		{ 
		 	cicle2++;
				 if (cicle2>30000)
				 {
				  cicle2=0;
				  led2=!led2; 
				 }
        } 
} 

void task3()
{ 
        while(1)
		{ 
		  if(key==0)
		   cicle2=10000;
	   //  cicle1=10000;
        } 
} 

void Timer0_Isr(void) interrupt 1	 //时间中断。调度任务。
{
         EA=0; //进入核心临界区关中断
         task_sp[current_id] = SP; 		//将进入时钟中断时的sp存入任务槽。
         if(++current_id == MAX_TASKS) 	//当前任务指向下一个任务号。如果任务号超过任务总数
			current_id=0;				//指向任务0;
		    SP = task_sp[current_id];	//把新任务的pc地址给sp,这样在时间中断出函数的时候系统自动把sp指向的值作为pc高8位;并出栈。
		 EA=1; //开中断。
}
void main()
{
	  
        //这里装载了三个个任务,因此在文件首部定义MAX_TASKS时也必须定义为3 
        task_load(task1, 0);//将task1函数装入0号槽,任务可以装入任意槽。 
        task_load(task2, 1);//将task2函数装入1号槽 
		task_load(task3, 2);//将task3函数装入2号槽 
	    Timer0_Init();		//定时器0初始化
	    key=1;				//口线置位。
		TR0 = 1;			//开始计时
        os_start();         //必须从任务在0号槽的任务开始;
		
 

}

虽然简单,也可以继续学习了。

相关推荐
普中科技6 小时前
【普中STM32F1xx开发攻略--标准库版】-- 第 45 章 FSMC-外扩 SRAM 实验
stm32·单片机·嵌入式硬件·fsmc·普中科技·外扩sram·is62wv51216
三佛科技-187366133979 小时前
FT32F103C8AT7兼容GD32F103C8T632 位通用微控制器MCU,替代性分析
单片机·嵌入式硬件
iCxhust9 小时前
8086汇编 word ptr
汇编·单片机·嵌入式硬件·微机原理·8088单板机
嵌入式ZYXC10 小时前
第3篇:《面试题:I2C为什么要加上拉电阻?阻值怎么选?》
stm32·单片机·嵌入式硬件·面试·职场和发展
leo__52010 小时前
C# 虚拟键盘(软键盘)实现
单片机·c#·计算机外设
你疯了抱抱我11 小时前
【STM32】使用 STM32CubeMX 生成项目,LED测试;上位机:STM32F411CEU6
stm32·单片机·嵌入式硬件
今天的你比昨天进步了?13 小时前
单片机程序,keil可以正常编译,VScode编译报错处理
vscode·单片机·嵌入式硬件
嵌入式小站13 小时前
STM32 零基础可移植教程 24:SPI Flash 读数据,先从指定地址读几个字节
chrome·stm32·嵌入式硬件
崇山峻岭之间14 小时前
单片机汉字显示实验
单片机·嵌入式硬件