基于网上网友的代码,自己在单片机上实现, 特此记录分享之。

基于https://blog.csdn.net/yyx112358/article/details/78877523

//使用KEIL C51实现的简单合作式多任务操作系统内核

#include <regx52.H>
#include <INTRINS.H> typedef unsigned char u8;
typedef unsigned int u16; sbit LED1 = P2 ^ 0;
sbit LED2 = P2 ^ 1;
sbit LED3_idle = P2 ^ 3; //两个宏定义是为了保护现场,不被定时中断打乱。
//主要用于需要一次性运行完毕的代码中。
#define OPEN_SYS_ISR() {EA=1;TR2=1;}
#define CLOSE_SYS_ISR() {EA=0;TR2=0;TF2=0;} #define OS_TASK_STACK_SIZE (2+13+2*3)//存放断点2B,中断函数可能压栈13B,子程序每嵌套一层2B #define OS_TASK_NUM 2 typedef struct OS_TASK_ST
{
u8 delay; //当前延时剩余时间
u8 stack[OS_TASK_STACK_SIZE]; //私有堆栈
u8 sp; //私有堆栈指针
} OS_TASK; //任务工作块。 data OS_TASK os_task[OS_TASK_NUM]; //必须定义为data(因堆栈只能在data区)
data u8 os_idle_stack[15]; void os_switch(void);
void os_idle(void);
//void os_update_time(void);
void os_load(u8 id, void(*func));
void os_delay(u8 id, u8 delay);
void LED_Driver();
void os_task_0(void);
void sys_init(void);
void delay(u16 i); /*******************************************************************************
* 函 数 名 : Timer2 Init
* 函数功能 : 定时器0初始化,用于系统时钟
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer2_init()
{
RCAP2H = (0xFFFF - 10000) / 256;
RCAP2L = (0xFFFF - 10000) % 256; //12MHz晶振下定10ms,自动重装
TH2 = RCAP2H;
TL2 = RCAP2L; //定时器2赋初值
T2CON = 0; //配置定时器2控制寄存器,这里其实不用配置,T2CON上电默认就是0,这里赋值只是为了演示这个寄存器的配置
T2MOD = 0; //配置定时器2工作模式寄存器,这里其实不用配置,T2MOD上电默认就是0,这里赋值只是为了演示这个寄存器的配置 IE = 0xA0; //1010 0000开总中断,开外定时器2中断,可按位操作:EA=1; ET2=1;
TR2 = 1; //启动定时器2
} void LED_Driver()
{
LED1 = ~LED1;
} void os_idle(void)
{
while (1)
{
LED3_idle = ~LED3_idle;
os_switch();
}
} /*
*任务调度,转向当前延时时间到且优先级最高(id较小)任务
而在一般的应用中,我们往往需要一个软件延时。例如:按键去抖、周期性采样等等。
所以,这就要求有一个软件定时器功能。因此,修改调度器如下:
首先定义任务控制器数据结构,加入一个延时记录:
*/
void os_switch(void)//任务切换
{
u8 i = OS_TASK_NUM;
do
{
i--;
if (os_task[i].delay == 0)//如果有任务延时时间到,则跳转至相应任务
SP = os_task[i].sp;
}
while (i); //否则不改变SP,继续执行os_idle()
} /*
* 更新任务延时表
* 注:应定时更新,最好放入定时器中断 void os_update_time(void)
{
u8 i = OS_TASK_NUM;
do
{
i--;
if(os_task[i].delay)
os_task[i].delay--;
}
while(i);
}
*/ //修改任务工作块并跳转入os_idle()进行任务切
void os_delay(u8 id, u8 delay)
{
TR2 = 0;//关中断
{
os_task[id].delay = delay; //延时设定
os_task[id].sp = SP; //保存SP
SP = os_idle_stack + 1; //SP指向os_idle_stack[1]
//os_delay()结束后跳转os_idle()
}
TR2 = 1;
} void os_load(u8 id, void(*func))
{
os_task[id].sp = os_task[id].stack + 1; //私有堆栈指针指向私有堆栈
os_task[id].stack[0] = (u16)func & 0xFF;//私有堆栈栈底存放任务函数入口
os_task[id].stack[1] = (u16)func >> 8;
} void os_task_0(void)
{
#define OS_CUR_ID (0) //static u8 i=0; //KEIL一般分配临时变量在RAM不在堆栈
//因此为了防止任务之间改写凡是作用域跨越os_delay()应作为static while (1)
{
LED1 = ~ LED1;
os_delay(OS_CUR_ID, 1);
} #undef OS_CUR_ID
} void os_task_1(void)
{
#define OS_CUR_ID (1) //static u8 i=0; //KEIL一般分配临时变量在RAM不在堆栈
//因此为了防止任务之间改写凡是作用域跨越os_delay()应作为static while (1)
{
//LED_Driver();
LED2 = ~ LED2;
os_delay(OS_CUR_ID, 1);
} #undef OS_CUR_ID
} /*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while (i--);
} void sys_init()
{
u8 i;
for (i=0; i<4; i++)
{
LED_Driver();
delay(10000);
}
} void main()
{
//…初始化外设
sys_init(); //…初始化os所用定时器 Timer2_init(); //…初始化其它任务控制器
os_load(0, os_task_0);
os_load(1, os_task_1); os_idle_stack[0] = (u16)os_idle & 0xFF;
os_idle_stack[1] = (u16)os_idle >> 8;
SP = os_task[0].sp; //运行任务0 return; //跳转,永不返回。
} //12MHz晶振下定10ms,自动重装
void timer2() interrupt 5
{
u8 i = OS_TASK_NUM;
//EA=0;
//ET2=0;
//TF2=0;
//!!!注意!!!定时器2必须由软件对溢出标志位清零,TF2=0;硬件不能清零,
//这里与定时器0和定时器1不同!!!
CLOSE_SYS_ISR(); do
{
i--;
if (os_task[i].delay)
os_task[i].delay--;
}
while (i); OPEN_SYS_ISR();
}

使用KEIL C51实现的简单合作式多任务操作系统内核(单片机实现版本)的更多相关文章

  1. 编写和运行简单的"Hello World"操作系统内核

    通常编写一个操作系统内核是一项浩大的工程.但我今天的目标是制作一个简单的内核,用比较方便的方法在虚拟机上验证它能够被grub装载和运行,并且可通过gdb进行调试,为接下去的工作创造一个基础环境. 首先 ...

  2. Keil C51编译及连接技术

    主要介绍Keil C51的预处理方法如宏定义.常用的预处理指令及文件包含指令,C51编译库的选择及代码优化原理,C51与汇编混合编程的方法与实现以及超过64KB空间的地址分页方法的C51实现. 教学目 ...

  3. keil c51笔记

    第一章 Keil C51开发系统基本知识 第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性. ...

  4. Keil C51程序调试过程

    用Keil C51编写程序时,经常需要调试,如果不是经常用这个软件的话,很容易忘记这些调试步骤,现在举一个例子“验证延迟函数delay()使其延迟的时间为500ms”说明. 源程序写完后,就可以调试了 ...

  5. Keil C51软件的使用

    进入 Keil C51 后,屏幕如下图所示.几秒钟后出现编辑界 启动Keil C51时的屏幕 进入Keil C51后的编辑界面 简单程序的调试:学习程序设计语言.学习某种程序软件,最好的方法是直接操作 ...

  6. Keil C51总线外设操作问题的深入分析

    阅读了<单片机与嵌入式系统应用>2005年第10期杂志<经验交流>栏目的一篇文章<Keil C51对同一端口的连续读取方法>(原文)后,笔者认为该文并未就此问题进行 ...

  7. KEIL C51 中嵌入汇编以及C51与A51间的相互调用

    如何在 KEIL C51(v6.21) 中调用汇编函数的一个示例 有关c51调用汇编的方法已经有很多帖子讲到,但是一般只讲要点,很少有对整个过程作详细描述,对于初学者是不够的,这里笔者通过一个简单例子 ...

  8. Hash查找法在Keil C51中的实现

    摘要:散列(hash)是一种重要的存储方法,也是一种常见的查找方法.它是指在记录的存储位置和它的关键字之间建立一个确定的对应关系.本文以射频卡门禁控制器为例,说明用射频卡卡号作为关键字,用Hash查找 ...

  9. KEIL C51高级编程

    第一节 绝对地址访问C51提供了三种访问绝对地址的方法: 1. 绝对宏:在程序中,用“#include”即可使用其中定义的宏来访问绝对地址,包括:CBYTE.XBYTE.PWORD.DBYTE.CWO ...

随机推荐

  1. python基础:10.多线程装饰器模式下的单例模式

    with def __enter__ def __close__ 闭包: 装饰器: 闭包的延迟绑定: 单例模式的应用:

  2. Python中的"Special Method"

    The first thing to know about special methods is that they are meant to be called by the Python inte ...

  3. vue 全局 js 方法

    1.新增 getCurrentDataType.js 文件 import cookieUtils from '@/config/cookieUtils' function getCurrentData ...

  4. WRNavigationBar 使用记录

    最近在做一个导航栏透明度渐变的效果,发现 WRNavigationBar库很好用,一开始导入到项目,发现导航tiltle颜色一直是黑色的,无论怎么用系统方法改都改不了.后来发现原来库里面有一个方法可以 ...

  5. signer information does not match signer information of other classes in the same package

    报错日志: java.lang.SecurityException: class "org.bouncycastle.asn1.ASN1ObjectIdentifier"'s si ...

  6. Codeforces Round #578 (Div. 2) E. Compress Words (双哈希)

    题目:https://codeforc.es/contest/1200/problem/E 题意:给你n个单词,你需要把他合成成一个句子,相邻的两个单词,相邻部分相同的话可以把其中一个的删掉 思路:因 ...

  7. PPT技巧

    1.秋叶个人的PPT三分钟教程   http://www.pptfans.cn/315656.html 2.<说服力-让你的PPT会说话>秋叶 3.<三体> https://w ...

  8. js中Array方法重写(二):myForEach;myEvery;mySome;myFilter;myReduce

    一.myForEach //myForeach 数组每个元素都执行一次回调函数 Array.prototype.myForEach = function(callback){ for(var i = ...

  9. Linux 学习 (五) DNS配置

    没有配置DNS会引起的问题 yum命令 ssh命令等不能进行 错误: Could not resolve host: centos.ustc.edu.cn; 本文例子: CentOS7 下DNS配置 ...

  10. 软件-Axure:Axure RP

    ylbtech-软件-Axure:Axure RP Axure RP是一款专业的快速原型设计工具.Axure(发音:Ack-sure),代表美国Axure公司:RP则是Rapid Prototypin ...