Small RTOS51 应用实例和分析
实例简介
这是Small RTOS51 在DP-51PROC 实验仪上实现一个简单游戏的程序。
程序使用按键S7 发出“子弹”,而数码管每秒送出一个“8”,当子弹打中“8”,则“8”
消失,而每秒“8”就往右移动一格,每两秒就会从最左边产生一个“8”,每个子弹只能打
中一个“8”。其实,仅仅从上面的描述,我们就可以把它划分为几个任务了,显示、处理8
的产生和移动、产生子弹、子弹的移动、中弹的处理。读者在DP-51PROC 上的接线可以
参考实验16 的I2C 接线。
由于仅仅是一个例子用来说明如何使用RTOS 51 上编写程序,而不是研制一个产品,
所以程序有一些细节没有完善。读者可以自行完善它。
为了锻炼读者分析代码的能力,本章不再分析程序代码,由读者自己分析。如果读者能
够自行编写类似程序则说明读者已经初步具备在RTOS51 编写应用程序的能力了。
程序清单4.26 Os_cfg.h
/*************************************************************
** Small RTOS51(51)
** The Real-Time Kernel(For Keil c51)
**
** (c) Copyright 2002-2002, chenmingji
** All Rights Reserved
** V1.12.1
**---------文件信息-----------------------------------------------------------
**文 件 名: OS_CFG.H
*************************************************************/
#define OS_MAX_TASKS 6
/* 最大任务数1~16*/
#define OS_TICKS_PER_SEC 10
/* 声明1 秒系统节拍数*/
#define EN_USER_TICK_TIMER 0
/* 禁止(0)或允许(1)系统定时中断调用用户函数UserTickTimer() */
#define EN_OS_INT_ENTER 1
/* 禁止(0)或允许(1)中断嵌套管理*/
#define EN_TIMER_SHARING 1
/* 禁止(0)或允许(1)定时器中断调用OSTimeTick()*/
#define TICK_TIMER_SHARING 1
/* 定义进入多少次硬件中断为一次系统定时器软中断*/
#define EN_OS_Q 0
/* 禁止(0)或允许(1)消息队列*/
#define EN_OS_Q_CHK 0
/* 禁止(0)或允许(1)校验消息队列指针*/
#define OS_Q_MEM_SEL xdata
/* 消息队列存储空间选择,keil c51 有用,必须为idata、xdata */
/* 不是keil c51 时它必须为空格*/
#define EN_OS_Q_PENT 1
/* 禁止(0)或允许(1)等待队列中的消息*/
#define EN_OS_Q_ACCEPT 0
/* 禁止(0)或允许(1)无等待的从队列中取得消息*/
#define EN_OS_Q_POST 0
/* 禁止(0)或允许(1)FIFO 方式向对列发送消息*/
#define EN_OS_Q_POST_FRONT 1
/* 禁止(0)或允许(1)LIFO 方式向对列发送消息*/
#define EN_OS_Q_INT_POST 0
/* 禁止(0)或允许(1)中断中FIFO 方式相对列发送消息*/
#define EN_OS_Q_INT_POST_FRONT 1
/* 禁止(0)或允许(1)中断中LIFO 方式相对列发送消息*/
#define EN_OS_Q_NMsgs 1
/* 禁止(0)或允许(1)取得队列中消息数*/
#define EN_OS_Q_SIZE 0
/* 禁止(0)或允许(1)取得队列总容量*/
#define EN_OS_Q_FLUSH 0
/* 禁止(0)或允许(1)清空队列*/
#define EN_OS_SEM 1
/* 禁止(0)或允许(1)信号量*/
#define EN_OS_SEM_CHK 0
/* 禁止(0)或允许(1)校验信号量索引*/
#define OS_SEM_MEM_SEL idata
/* 信号量储空间选择,keil c51 有用,必须为idata、xdata */
/* 不是keil c51 时它必须为空格*/
#define OS_MAX_SEMS 2
/* 最大信号量数目*/
#define EN_OS_SEM_PENT 1
/* 禁止(0)或允许(1)等待信号量*/
#define EN_OS_SEM_ACCEPT 0
/* 禁止(0)或允许(1)无等待请求信号量*/
#define EN_OS_SEM_INT_POST 0
/* 禁止(0)或允许(1)中断中发送信号量*/
#define EN_OS_SEM_POST 1
/* 禁止(0)或允许(1)中发送信号量*/
#define EN_OS_SEM_QUERY 0
/* 禁止(0)或允许(1)查询信号量*/
#if EN_TIMER_SHARING == 0
#define TIME_ISR_TASK_ID SHOW_TASK_ID
/* 定义系统定时器软中断触发的任务ID*/
#endif
#ifdef IN_OS_CPU_C
#if EN_USER_TICK_TIMER > 0
extern void UserTickTimer(void);
/* 系统定时中断中调用的用户函数*/
#endif
#endif
/**********************end***********************************/
CPU 配置文件Os_cpu.h:
程序清单4.27 Os_cpu.h
/*************************************************************
** Small RTOS51
** The Real-Time Kernel For Keil c51
**
** (c) Copyright 2002-2002, chenmingji
** All Rights Reserved
** V1.12.1
**--------------文件信息------------------------------------------------------------
**文 件 名: OS_CPU.h
*************************************************************/
#define EN_SP2 0 /* 禁止(0)或允许(1)软非屏蔽中断*/
#ifdef __C51__
typedef unsigned char uint8;
/* 定义可移植的无符号8 位整数关键字*/
typedef signed char int8;
/* 定义可移植的有符号8 位整数关键字*/
typedef unsigned int uint16;
/* 定义可移植的无符号16 位整数关键字*/
typedef signed int int16;
/* 定义可移植的有符号16 位整数关键字*/
typedef unsigned long uint32;
/* 定义可移植的无符号32 位整数关键字*/
typedef signed long int32;
/* 定义可移植的有符号32 位整数关键字*/
#ifndef NULL
#define NULL 0
#endif
#if EN_OS_INT_ENTER >0
#define OS_INT_ENTER() OSIntNesting++,EA=1
#endif
#define OS_ENTER_CRITICAL() EA = 0,Os_Enter_Sum++
/* 禁止中断*/
#define OS_EXIT_CRITICAL() if (--Os_Enter_Sum==0) EA = 1
/* 允许中断*/
#define HIGH_BYTE 0 /* uint16 的高位字节*/
#define LOW_BYTE 1 /* uint16 的低位字节*/
#define OS_TASK_SW() OSCtxSw() /* 任务切换函数*/
#define IDATA_RAM_SIZE 0x100 /* idata 大小*/
extern void OSCtxSw(void);
extern void OSIntCtxSw(void);
#ifndef IN_OS_CPU_C
extern void OSStart(void);
#endif
#define Sp2Space 4
/* 高级中断(软非屏蔽中断)堆栈大小 EN_SP2 为0 时无效*/
#define OS_TIME_ISR 1
/*系统定时器使用的中断*/
#endif
#ifndef __C51__
SET_EA MACRO ;打开所有中断允许
SETB EA
ENDM
#endif
/*****************end****************************************/
24.2.3 用户配置文件Config.h:
程序清单4.28 Config.h
/*************************************************************
** Small RTOS51
** The Real-Time Kernel For Keil c51
**
** (c) Copyright 2002-2002, chenmingji
** All Rights Reserved
** V1.12.1
**--------------文件信息-------------------------------------------------------------
**文 件 名: CONFIG.H
*************************************************************/
/**********************************/
/* "以下为系统配置" */
/**********************************/
#pragma REGPARMS
#include
#include
#include
#define const code
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/**********************************/
/* "操作系统定义" */
/**********************************/
#include "OS_CFG.H"
#include "OS_CPU.H"
#include "..\os\OS.H"
#include "..\os\OS_Q.h"
#include "..\os\OS_SEM.h"
#include "VIIC_C51.h"
#include "zlg7290.h"
/**********************************/
/* "以下为程序配置" */
/**********************************/
//任务定义
#ifdef IN_OS_CPU_C
extern void TaskA(void);
extern void TaskB(void);
extern void TaskC(void);
extern void TaskD(void);
extern void TaskE(void);
extern void TaskF(void);
void (* const TaskFuction[OS_MAX_TASKS])(void)=
{ TaskA,TaskB,TaskC,TaskD,TaskE,TaskF };
//函数数组TaskFuction[]保存了各个任务初始PC 指针,其按任务ID 顺序保存
#endif
/**********************end***********************************/
ZLG7290 应用函数程序zlg7290.c
程序清单4.29 zlg7290.c
/*************************************************************
** Zlg7290 API
** Zlg7290 Application Program Interface
**
** (c) Copyright 2003-2004, Yehaoben
** All Rights Reserved
** V1.0
**--------------文件信息-------------------------------------------------------------
**文 件 名: zlg7290.c
*************************************************************/
#include "REG52.h"
#include "viic_c51.h"
#define zlg7290 0x70 /*ZLG7290 的I2C 地址*/
#define SubKey 0x01
#define SubCmdBuf 0x07
#define SubDpRam 0x10
/*************************************************************
** 函数名称: DelayNS
** 功能描述: 长软件延时
** 输 入: I : 延时参数,值越大时延时越久
** 输 出: 无
** 全局变量: 无
** 调用模块: 无
*************************************************************/
void delayMS(unsigned char i)
{
unsigned char j,k;
for(k=0;kfor(j=0;j<60;j++);
}
/*************************************************************
** 函数名称: ZLG7290_SendData
** 功能描述: 发送数据
** 输 入: SubAdd : 输入数据
** DATA : 输入值
**
** 输 出: 0 : Fail
** 1 : OK
** 全局变量: 无
** 调用模块: delayMS
*************************************************************/
unsigned char ZLG7290_SendData( unsigned char SubAdd,
unsigned char Data)
{
if(SubAdd>0x17)
return 0;
ISendStr(zlg7290,SubAdd,&Data,1);
delayMS(10);
return 1;
}
/*************************************************************
** 函数名称: ZLG7290_SendCmd
** 功能描述: 发送命令(对子地址7、8)
** 输 入: DATA1 : 命令1
** DATA2 : 命令2
**
** 输 出: 0 : Fail
** 1 : OK
** 全局变量: 无
** 调用模块: ISendStr、delayMS
*************************************************************/
unsigned char ZLG7290_SendCmd( unsigned char Data1,
unsigned char Data2)
{
unsigned char Data[2];
Data[0]=Data1;
Data[1]=Data2;
ISendStr(zlg7290,0x07,Data,2);
delayMS(10);
return 1;
}
/*************************************************************
** 函数名称: ZLG7290_SendBuf
** 功能描述: 向显示缓冲区发送数据
** 输 入: * disp_buf : 要发送的数据的起始地址
** num : 发送个数
**
** 输 出: 无
** 全局变量: 无
** 调用模块: ZLG7290_SendCmd
*************************************************************/
void ZLG7290_SendBuf(unsigned char * disp_buf,unsigned char num)
{
unsigned char i;
for(i=0;i
ZLG7290_SendCmd(0x60+i,*disp_buf);
disp_buf++;
}
}
/*************************************************************
** 函数名称: ZLG7290_SendBuf1
** 功能描述: 向显示缓冲区发送非译码数据
** 输 入: * disp_buf : 要发送数据的起始地址
** num : 发送字节个数
**
** 输 出: 无
** 全局变量: 无
** 调用模块: ISendStr
*************************************************************/
void ZLG7290_SendBuf1(unsigned char * disp_buf,unsigned char num)
{
ISendStr(zlg7290,0x10,disp_buf,num);
}
/*************************************************************
** 函数名称: ZLG7290_GetKey
** 功能描述: 读取键值
** 输 入: 无
**
** 输 出: >0 键值
** =0 无键按下
** 全局变量: 无
** 调用模块: IRcvStr、delayMS
*************************************************************/
unsigned char ZLG7290_GetKey()
{
unsigned char rece;
rece=0;
IRcvStr(zlg7290,1,&rece,1);
delayMS(10);
return rece;
}
/**********************end***********************************/
4.4.5 主程序EXT1.c
程序清单4.30 EXT1.c
/*************************************************************
** Small RTOS51_Example
** The Game For Small RTOS51
**
** (c) Copyright 2003-2004, Yehaoben
** All Rights Reserved
** V1.0
**--------------文件信息-------------------------------------------------------------
**文 件 名: EXT1.c
*************************************************************/
#include "config.h"
void DISPLAY(unsigned char * disp);
/*全局变量*/
uint8 key=0xff;
uint8 disp_buf[8]={0x08,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0F};
void main(void)
{
TMOD = (TMOD & 0XF0) | 0X01;
TL0 = 0x0;
TH0 = 0x80;
TR0 = 1;
ET0 = 1;
TF0 = 0;
DISPLAY(disp_buf);
EX0=1;
TI=1;
OSSemCreate(0,1);
OSStart();
}
/*键盘中断服务函数*/
void int_ex1() interrupt 0
{
OS_INT_ENTER();
OS_ENTER_CRITICAL();
key=ZLG7290_GetKey(); //读取键值
OS_EXIT_CRITICAL();
OSIntExit();
}
/*显示任务*/
void TaskA(void)
{
while (1)
{
OS_ENTER_CRITICAL();
DISPLAY(disp_buf); /*显示*/
OS_EXIT_CRITICAL();
OSWait(K_TMO,1);
}
}
/*8 的移动和产生任务*/
void TaskB(void)
{
uint8 x,y;
x=0;
while (1)
{
OS_ENTER_CRITICAL();
for(y=0;y<8;y++)
{
if(disp_buf[y]==8)
{
disp_buf[y]=0x0f;
disp_buf[y+1]=0x08; /*8往左移动一位*/
y++;
}
}
if(x==0)
{
disp_buf[0]=0x0f; /*使终点不断出8*/
x=1;
}
else
{
disp_buf[0]=0x08;
x=0;
}
OS_EXIT_CRITICAL();
OSWait(K_TMO,15);
}
}
/*接收按键任务*/
void TaskC(void)
{
uint8 x=0XFF;
while (1)
{
x=key;
if(x==0x07) /*如果有键值键入就发出发弹命令*/
{
x=0xff;
key=0xff;
OSSemPost(0);
}
OSWait(K_TMO,1);
}
}
/*发子弹任务*/
void TaskD(void)
{
uint8 y;
while (1)
{
if(OSSemPend(0,0)==OS_SEM_OK) /*接收到发弹信号*/
{
OS_ENTER_CRITICAL();
disp_buf[7]=0x0a; /*发弹*/
for(y=0;y<7;y++)
if(disp_buf[y]==0x0a)
disp_buf[7]=0x0f;
OS_EXIT_CRITICAL();
}
OSWait(K_TMO,10);
}
}
/*子弹飞行任务*/
void TaskE(void)
{
uint8 y;
while (1)
{
OS_ENTER_CRITICAL();
for(y=8;y>1;y--)
{
if(disp_buf[y-1]==0X0A) /*弹向前飞行*/
{
disp_buf[y-1]=0x0F;
disp_buf[y-2]=0x0A;
y=1;
}
}
OS_EXIT_CRITICAL();
OSWait(K_TMO,3);
}
}
/*中弹处理任务*/
void TaskF(void)
{
uint8 y;
while (1)
{
OS_ENTER_CRITICAL();
for(y=6;y>0;y--)
{
if( ( disp_buf[y] == 0X08 ) && ( disp_buf[y+1] == 0X0A ) )
/*如果弹碰到8 就消失*/
{
disp_buf[y]=0x0F;
disp_buf[y+1]=0x0F;
}
}
OS_EXIT_CRITICAL();
OSWait(K_TMO,2);
}
}
/*显示函数,由于该函数为不可重入函数,所以调用前先关中断*/
void DISPLAY(unsigned char *disp)
{
unsigned char buff[8];
unsigned char i;
for(i=0;i<8;i++)
{
switch(disp[i])
{
case 0x0f :
buff[i]=0x00;
break;
case 0x08 :
buff[i]=0xfe;
break;
case 0x0a :
buff[i]=0x02;
break;
default :
buff[i]=0x00;
break;
}
}
ZLG7290_SendBuf1(buff,8);//显示
}
例子程序的其它部分请参考本书配套光盘的中的源代码。
Small RTOS51 源码下载链接:http://www.elecfans.com/soft/6/2008/200806264386.html
评论
查看更多