这两天没事想学RTOS,但是没有实时操作系统的概念,就想起以前看过的一篇文章,是在51系列单片机上建立一个简单的多任务实时操作系统RTOS,我就开始拿这个当台阶吧,让自己对多任务实时操作系统有个大概的认识,这样才能让自己不会被复杂的RTOS给吓倒。
我们在写51系列单片机程序时肯定有很多人跟我一样,只是把基础模块一个一个的实现,而不会很深入的去写,或许你能将它们组合,一般都是一个大循环while, 加一些延时Delay,但是你想过没,在你用while和Delay时你很犯了一个很大的错误,因为我们让MCU在处理Delay时白白的浪费了很多时间,因为MCU在等待Delay,也许你会说只是延时几s,或者几ms,但是你要知道我们的MCU是以us为单位工作的,在MCU等待的这段时间它可以处理很多事情了,所以如果在处理这些事情时加入一个实时操作系统,让RTOS帮我们合理分配MCU的时间。如果我们把这些事情当做RTOS的几个任务,并合理设置分配
RTOS的节拍和设置这些任务的执行频度,这就可以大大的提升了系统的速度和性能,这是以后写实用程序的最好开始。好了废话少说,进入主题~
在进入主题之前先说说我理解的几个概念:
系统任务:所谓任务,就是需要CPU 周期“关照”的事件,就是我们需要MCU做的事情。
实时操作系统:就是当外部产生事件时能及时快速处理,且根据处理结果在规定的时间之内作出相应的控制和响应,并控制所有实时任务协调一致运行的操作系统。
51系列的多任务实时操作系统有4个文件:
MAIN.c —— main 函数文件
OS.c —— 系统 相关函数文件
OS.h —— 系统 相关配置参数头文件
OS_TASK.c —— 用户任务task 函数文件
系统原理:单片机定时器延时中断来产生系统任务调度节拍,设置各个任务的执行频度,
来调度各任务。以实现系统多线 实时操作。
下面一一列出:
一、MAIN.c文件
/********************************
*FileName: MAIN_C
*Author: JZHG1992
*Versions: V1.0
*********************************/
#include "OS.h"
/************************************
* 主函数
*************************************/
void main( void )
{
uchar i;
OS_Timer0_Init(); // 系统定时器时钟初始化
EA = 1; // 开总中断
while(1)
{
for ( i=0; i<TASK_MAX; i++ )
{
if ( Task_Delay == 0 )
{
OS_Task_Run( task );
break;
}
}
}
}
二、OS.c文件
/********************************
*FileName: OS_C
*Author: JZHG1992
*Versions: V1.0
*********************************/
#include "OS.H"
/************************************
* 系统任务执行频度参数
*************************************/
uchar Task_Delay[TASK_MAX];
/************************************
* 系统定时器时钟初始化
*************************************/
void OS_Timer0_Init( void )
{
uchar i;
for ( i=0; i<TASK_MAX; i++ )
{
Task_Delay = 0; // 复位系统任务执行频度参数
}
TMOD = (TMOD&0xf0)|0x01; // 设置定时器0方式1
TH0 = 256-(OS_CLOCK/TASK_CLOCK)/12/256; // 赋初值200Hz
TL0 = 256-(OS_CLOCK/TASK_CLOCK)/12%256;
TR0 = 1; // 使能定时器0
ET0 = 1; // 使能定时器0中断
}
/************************************
* 系统任务调度函数
*************************************/
void OS_Task_Run( void (*ptask)() )
{
(*ptask)();
}
/************************************
* 系统中断服务函数
*************************************/
void OS_ISR( void ) interrupt 1
{
uchar i;
TH0 = 256-(OS_CLOCK/TASK_CLOCK)/12/256; // 赋初值200Hz
TL0 = 256-(OS_CLOCK/TASK_CLOCK)/12%256;
for ( i=0; i<TASK_MAX; i++ )
{
if ( Task_Delay )Task_Delay --;
}
}
三、OS.h文件
/********************************
*FileName: OS_H
*Author: JZHG1992
*Versions: V1.0
*********************************/
/********************************
*系统原理:单片机定时器延时中断来产
* 生系统任务调度节拍,设置
* 各个任务的执行频度,来调
* 度各任务。以实现系统多线
* 操作。
*********************************/
#ifndef _OS_H_
#define _OS_H_
#include<reg52.h>
/************************************
* 定义变量类型
*************************************/
#define uchar unsigned char // 宏定义uchar
#define uint unsigned int // 宏定义uint
/************************************
* 配置系统参数
*这里你可以根据你的需要修改
*************************************/
#define OS_CLOCK 12000000 // 系统晶振频率,单位Hz
#define TASK_CLOCK 200 // 任务中断节拍,单位Hz
#define TASK_MAX 2 // 任务数目
/************************************
* 系统任务外调函数与参数
*************************************/
extern uchar Task_Delay[TASK_MAX]; // 系统任务执行频度参数
extern void OS_Timer0_Init( void ); // 系统定时器时钟初始化
extern void OS_Task_Run( void(*ptask)()); // 系统任务调度函数
extern void ( *const task[] )(); // 获得任务指针
//-------------
#endif
四、OS_TASK.c文件
/********************************
*FileName: TASK_C
*Author: JZHG1992
*Versions: V1.0
*********************************/
#include "OS.H"
/************************************
* 设置系统任务执行频度
* 根据自己任务分配执行频度
*************************************/
#define TASK_DELAY0 TASK_CLOCK/10 // 任务0的执行频度
#define TASK_DELAY1 TASK_CLOCK/1 // 任务1的执行频度
/* ........ */
#defien TASK_DELAYn TASK_CLOCK/1 // 任务n的执行频度
/************************************
* 任务0函数
*************************************/
void task0( void )
{
Task_Delay[0] = TASK_DELAY0; // 设置任务执行度
/* 你的任务*/
/* ..... */
}
/************************************
* 任务1函数
*************************************/
void task1( void )
{
Task_Delay[1] = TASK_DELAY1; // 设置任务执行度
/* 你的任务*/
/* ...... */
}
/************************************
* 任务n( n=TASK_MAX -1 )函数
*************************************/
void taskn( void )
{
Task_Delay[n] = TASK_DELAYn; // 设置任务执行度
/* 你的任务*/
/* ...... */
}
/************************************
* 获得任务指针
*************************************/
void ( *const task[] )() = { task0, task1,..taskn };
//--------------------------------------------------------------
配置过程:
1、设置的只有OS.h文件中的
/************************************
* 配置系统参数
*这里你可以根据你的需要修改
*************************************/
#define OS_CLOCK 12000000 // 系统晶振频率,单位Hz
#define TASK_CLOCK 200 // 任务中断节拍,单位Hz
#define TASK_MAX 2 // 任务数目
/************************************
2、设置OS_TASK.c文件中的
/************************************
* 设置系统任务执行频度
* 根据自己任务分配执行频度
*************************************/
#define TASK_DELAY0 TASK_CLOCK/10 // 任务0的执行频度
#define TASK_DELAY1 TASK_CLOCK/1 // 任务1的执行频度
/* ........ */
#defien TASK_DELAYn TASK_CLOCK/1 // 任务n的执行频度
3、将我的任务加进来
/************************************
* 任务0函数
*************************************/
void task0( void )
{
Task_Delay[0] = TASK_DELAY0; // 设置任务执行度
/* 你的任务*/
/* ..... */
}
/************************************
* 任务1函数
*************************************/
void task1( void )
{
Task_Delay[1] = TASK_DELAY1; // 设置任务执行度
/* 你的任务*/
/* ...... */
}
/************************************
* 任务n( n=TASK_MAX -1 )函数
*************************************/
void taskn( void )
{
Task_Delay[n] = TASK_DELAYn; // 设置任务执行度
/* 你的任务*/
/* ...... */
}
4、 提取任务的函数指针
/************************************
* 获得任务指针
*************************************/
void ( *const task[] )() = { task0, task1,..taskn };
这个多任务实时操作系统虽然很简单,但是他让我知道了一些多任务实时操作系统的一些概念,让我跟有信心的去迎接更复杂、功能更强大的多任务实时操作系统,也希望对跟我一样很菜的“电子人”一些启发,也希望有兴趣的朋友可以跟我交流~~