一个简单的51单片机操作系统的实现

发布者:Joyful888Life最新更新时间:2012-08-15 来源: 51hei关键字:51单片机  操作系统  进程管理 手机看文章 扫描二维码
随时随地手机看文章

复习到操作系统这本书,在看到进程管理的时候,想起以前费了相当大的时间去做一个属于自己的操作系统,结果什么都没弄出来。

趁着看到这个章节,又一次地萌生了这个想法,于是网上各种寻找资料。发现现在的大多数操作系统都已经比较完善,换而言之,就是太庞大。无法去理解,无法自己照搬原文去弄一个属于自己的操作系统出来。

机缘偶得之下,发现了一篇关于在单片机下面实现一个实时操作系统的文章, 即《建立一个属于自己的AVR的RTOS》,这篇文章比起讲什么操作系统原理、unix内核分析、linux内核分析、xx内核分析等等来说,简单明了了很多(有兴趣的同学们可以去研究一下这篇文章)。在参考这篇文章以及在51单片机下面使用汇编语言编程,以及众多网上资料之后。总结地写出了一个"在51单片机下具有延时功能占先式内核的操作系统“,并仿真成功,加深了我对操作系统这个东西的小小理解。下面附上程序代码以及实现。
如果网页复制代码有错误,操作系统的完整代码请从这里下载:http://www.51hei.com/f/12545.rar

[page]

以下是部分代码:

#include 

#define MAX_TASKS 5

typedef struct os_task_control_table {
unsigned char os_task_wait_tick;
unsigned char os_task_stack_top;
}TCB;

volatile unsigned char int_count;
volatile unsigned char os_en_cr_count;
#define enter_int() EA=0;int_count++;
#define os_enter_critical() EA=0;os_en_cr_count++;
#define os_exit_critical() if(os_en_cr_count>=1)
{os_en_cr_count--;if(os_en_cr_count==0)EA=1;}
unsigned char code os_map_tbl[] = {0x01, 0x02, 0x04,
 0x08, 0x10, 0x20, 0x40, 0x80};

volatile unsigned char os_task_int_tbl;
idata volatile TCB os_tcb[MAX_TASKS];
volatile unsigned char os_task_running_id;
volatile unsigned char os_task_rdy_tbl;
unsigned char idata os_task_stack[MAX_TASKS][20];

void os_init(void);
void os_task_create(unsigned char task_id ,
unsigned int task_point,unsigned char stack_point);
void os_delay(unsigned char ticks);
void os_start(void);
void os_task_switch(void);
void exit_int(void);

void os_init(void) {
EA = 0;
ET2 = 1;
T2CON = 0X00;
T2MOD = 0X00;
RCAP2H = 0x0D8;
RCAP2L = 0x0F0;
os_task_rdy_tbl = 0;
os_task_int_tbl = 0xff;
int_count = 0;
os_en_cr_count = 0;
}

void os_task_create(unsigned char task_id ,
unsigned int task_point,unsigned char stack_point) {
os_enter_critical();
((unsigned char idata *)stack_point)[0] = task_point;
((unsigned char idata *)stack_point)[1] = task_point>>8;
os_tcb[task_id].os_task_stack_top = stack_point+14;
os_task_rdy_tbl |= os_map_tbl[task_id];
os_tcb[task_id].os_task_wait_tick = 0;
os_exit_critical();
}

void os_delay(unsigned char ticks) {
os_enter_critical();
os_tcb[os_task_running_id].os_task_wait_tick = ticks;
os_task_rdy_tbl &= ~os_map_tbl[os_task_running_id];
os_exit_critical();
os_task_switch();
}

void os_start(void) {
os_task_running_id = 0;
os_tcb[os_task_running_id].os_task_stack_top -= 13;
EA = 1;
SP = os_tcb[os_task_running_id].os_task_stack_top;
TR2 = 1;
}

void os_task_switch(void) {
unsigned char i;
EA = 0;
os_tcb[os_task_running_id].os_task_stack_top = SP;
os_task_int_tbl &= ~os_map_tbl[os_task_running_id];
for(i=0; i0; x--)
for(y=248; y>0; y--);
}
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0};
void task_1(void) {
unsigned char gw,sw,bw;
while(1) {
bw = os_tcb[2].os_task_wait_tick/100;
sw = os_tcb[2].os_task_wait_tick%100/10;
gw = os_tcb[2].os_task_wait_tick%10;
P0 = table[bw];
seg2=0;
delay_ms(3);
seg2=1;
P0 = table[sw];
seg3=0;
delay_ms(3);
seg3=1;
P0 = table[gw];
seg4=0;
delay_ms(3);
seg4=1;
}
}

void task_2(void) {
unsigned char i;
while(1) {
i++;
P3 = 0x01<<(i%8);
os_delay(200);
}
}

void task_3(void) {
unsigned char i;
while(1) {
i++;
//P2 = 0x01<<(i%8);
os_delay(7);
}
}

void task_4(void) {
unsigned char i;
while(1) {
i++;
P1 = 0x01<<(i%8);
  os_delay(10);
}
}

void main(void) {
os_init();
os_task_create(4,(unsigned int)&task_0,(unsigned char)os_task_stack[4]);
os_task_create(3,(unsigned int)&task_1,(unsigned char)os_task_stack[3]);
os_task_create(2,(unsigned int)&task_2,(unsigned char)os_task_stack[2]);
os_task_create(1,(unsigned int)&task_3,(unsigned char)os_task_stack[1]);
os_task_create(0,(unsigned int)&task_4,(unsigned char)os_task_stack[0]);
os_start();
}

实现的图片:

 点击浏览下一页
 

[page]

讲解一下实现的内容:

task_0是个空循环

task_1的作用是提取task_2的等待时间,显示在数码管上

task_2是在P3口上的跑马灯(2秒跑一个灯)

task_3是单纯地调用任务延时

task_4在P1口上的跑马灯(100ms跑一个灯)


程序使用定时器2计数器产生的中断作为时钟源,时钟的节拍是10ms一次。

 

当然这个渺小的操作系统只实现了一些相当基本的功能:多任务和系统延时以及抢占优先级。还有信号量、内存管理、事件、邮箱等等机制尚未实现,但是懂了这个基础内容之后,其它的东西,都是在上面做扩充的。

记得在一篇资料里面听到过这个:会写状态机的程序员,肯定会写操作系统。这句话到现在觉得相当正确。操作系统就是一个另类的状态机,人为地干预了子程序调用和返回的过程。庆幸当年的汇编没白学,操作系统需要懂得一些基本的硬件结构,汇编,C语言,当懂得这些之后,再去网上多搜索点相关的资料,并且自己去用代码一行行实现,加以时日,操作系统便能轻松地玩转与手.


在此,感谢黄健昌在网上的发表的《 建立一个属于自己的AVR的RTOS》,这篇文章让我对RTOS有了一个浅显的了解

风城少主发表的《建立一个属于自己的51实时操作系统》,指导我在熟悉的51单片机上实现这个操作系统。

芯源老师的《芯源的单片机教程》为我提供了51单片机汇编及其硬件架构的深入了解。

感谢http://www.51hei.com/mcu/1111.html 这个作者的激励与鼓励

真诚地感谢上面提及的人,让我能够入门操作系统,进而了解到什么是嵌入式操作系统,怎么去具体实现。

关键字:51单片机  操作系统  进程管理 引用地址:一个简单的51单片机操作系统的实现

上一篇:基于stc89c52rc单片机的数字钟设计(数码管显示)
下一篇:基于单片机控制12864显示矩阵键盘输入的计算器

推荐阅读最新更新时间:2024-03-16 13:05

基于STC89C51单片机的数字电压表设计
0 引言 数字电压表的设计和开发已有很多类型和款式,传统的数字电压表有自己的特点,它们适合在现场做手工测量,而要完成远程测量并对测量的数据做进一步处理,运用传统的数字电压表是无法完成的。为此,本文设计了基于PC通信的数字电压表,该表既可以完成测量数据的传递,又可借助PC进行测量数据的处理。所以,这种类型的数字电压表无论在功能和实际应用上,都具有传统数字电压表无法比拟的优点,这使得它的开发和应用都具有良好的前景。 1 系统构成 本系统主要由硬件和软件两部分构成,硬件主要包括数据采集电路,单片机最小数据采集系统,单片机与PC机的接口电路等。软件主要有单片机数据采集程序,单片机与上位机通信程序,以及上位机数据处理程序。
[单片机]
51单片机学习——1--点亮第一个LED
点亮LED 原理: 此单片机的LED灯就是个发光二极管,只能单向通行。图中LED阴极接IO口,阳极接VCC,也就是电源,为高电平,而正常情况下P2口默认输出高电平,所以只需令P2口输出低点平即可。 代码: #include reg52.h sbit led=P2^0;//通过位定义,令led代表P20口 void main() { while(1) { led=0;//令P20为低电平 } } 总结: 知识点: 设置管脚sbit name=Px^x(IO口) 令目标led灯对应的IO口输出低电平 拓展: 也可以直接对P2的所有IO口进行赋值输出。即1111 1111从高位到低位分别对应从左到右
[单片机]
<font color='red'>51单片机</font>学习——1--点亮第一个LED
P10点阵屏C51单片机程序
P10点阵屏C51程序 1/4扫描,四扫下行,1路16行,数据低OE高(04-P16-08) 适用于HUB12接口单色P10 串口模式0,普通左移,亮度速度可调,6个IO口,用的STC8F1K08,最多231个字 制作出来的实物图如下: 单片机源程序如下: #include STC8.H #include intrins.h #include string.h #define DATA P30 // #define CLOCK P31 //↑ ↓ #define ADDR_A P32 //↑ #de
[单片机]
P10点阵屏C<font color='red'>51单片机</font>程序
51单片机的中断响应原理
1.中断概念 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生); CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务); 待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断。 2.中断系统结构 引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统。 89C51/52的中断系统有5个中断源 ,2个优先级,可实现二级中断嵌套 。 (P3.2)可由IT0(TCON.0)选择其为
[单片机]
<font color='red'>51单片机</font>的中断响应原理
51单片机之C语言-4.1数据类型
从这一章起我们开始学习单片机C语言,既然是语言那么就应该有基本词汇和相关的语法。我们先来看看数据类型。讲数据之前先简单说说单片机的存储结构。我们知道单片机要运行之前,我们需要给他写指令,指令存放在ROM存储器上。我们再细想一下,既然存放在ROM上,那么我们来想一个问题,比如我的指令中有个数字 3 要,这个 3 是怎么存放的?相信这个很容易,单片机中存放的都是二进制,那么首先要转成二进制11B,格式如下: 这个不就是表示3了吗?也就是说,如果你要放这个数,我把这个数先转成二进制形式(可以直接使用电脑自带的计算机来转换),然后找单片机的存储器要2个格子放进去1或者0就行了。这样理解对不对呢?不对。你向单片机要格子的时候,单片机要
[单片机]
<font color='red'>51单片机</font>之C语言-4.1数据类型
Proteus仿真51单片机C语言程序实例-开关控制报警器
简介:51单片机C语言程序实例-开关控制报警器(用K1开关控制报警器,程序控制P1.0输出两种不同频率的声音,模拟很逼真的报警效果)。
[单片机]
Proteus仿真<font color='red'>51单片机</font>C语言程序实例-开关控制报警器
c51单片机第一课笔记
1,串口 并口的区别 串行接口,简称串口,也就是COM接口,是采用串行通信协议的扩展接口。串口的出现是在1980年前后,数据传输率是115kbps~230kbps,串口一般用来连接鼠标和外置Modem以及老式摄像头和写字板等设备,目前部分新主板已开始取消该接口。 并行接口,简称并口,也就是LPT接口,是采用并行通信协议的扩展接口。并口的数据传输率比串口快8倍,标准并口的数据传输率为1Mbps,一般用来连接打印机、扫描仪等。所以并口又被称为打印口。 2什么是下拉电阻 什么是上拉电阻分别的作用。 3 ttl电平 5型号介绍 stc89c52 40c-pdip 0721cv4336 c 是指cmos 52 51 55 52 2x4k
[单片机]
基于MCS-51单片机的智能机器人迷宫车设计
摘要:机器人在军事侦察、扫雷排险、防核化污染等危险与恶劣环境中以及工业自动化生产的物料搬运上应用很广,随着任务复杂性的增加,对移动机器人的要求也越来越智能化。然而,功能较完备的路径跟踪控制方法普遍具有计算复杂,不易实现等特点。主要针对移动机器人即智能小车的行走系统进行设计,以MCS-51单片机为控制核心的智能小车利用单光束反射取样红外传感器,探测正前方及左右两侧障碍物,利用控制算法寻找行进路线,在无人控制的情况下自主地走出迷宫。设计采用了轮式移动机构,使机器人能直线行走、左右转弯、主要针对路径跟踪算法优化问题,提出一种有效可行的方法,该法比以往算法更简单易行。 关键词:智能小车;迷宫;控制算法;避障 机器人应当具有几个特征:移动
[工业控制]
基于MCS-<font color='red'>51单片机</font>的智能机器人迷宫车设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved