Small RTOS51 應(yīng)用實例和分析
實例簡介
這是Small RTOS51 在DP-51PROC 實驗儀上實現(xiàn)一個簡單游戲的程序。
程序使用按鍵S7 發(fā)出“子彈”,而數(shù)碼管每秒送出一個“8”,當(dāng)子彈打中“8”,則“8”
消失,而每秒“8”就往右移動一格,每兩秒就會從最左邊產(chǎn)生一個“8”,每個子彈只能打
中一個“8”。其實,僅僅從上面的描述,我們就可以把它劃分為幾個任務(wù)了,顯示、處理8
的產(chǎn)生和移動、產(chǎn)生子彈、子彈的移動、中彈的處理。讀者在DP-51PROC 上的接線可以
參考實驗16 的I2C 接線。
由于僅僅是一個例子用來說明如何使用RTOS 51 上編寫程序,而不是研制一個產(chǎn)品,
所以程序有一些細節(jié)沒有完善。讀者可以自行完善它。
為了鍛煉讀者分析代碼的能力,本章不再分析程序代碼,由讀者自己分析。如果讀者能
夠自行編寫類似程序則說明讀者已經(jīng)初步具備在RTOS51 編寫應(yīng)用程序的能力了。
程序清單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
/* 最大任務(wù)數(shù)1~16*/
#define OS_TICKS_PER_SEC 10
/* 聲明1 秒系統(tǒng)節(jié)拍數(shù)*/
#define EN_USER_TICK_TIMER 0
/* 禁止(0)或允許(1)系統(tǒng)定時中斷調(diào)用用戶函數(shù)UserTickTimer() */
#define EN_OS_INT_ENTER 1
/* 禁止(0)或允許(1)中斷嵌套管理*/
#define EN_TIMER_SHARING 1
/* 禁止(0)或允許(1)定時器中斷調(diào)用OSTimeTick()*/
#define TICK_TIMER_SHARING 1
/* 定義進入多少次硬件中斷為一次系統(tǒng)定時器軟中斷*/
#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 方式向?qū)α邪l(fā)送消息*/
#define EN_OS_Q_POST_FRONT 1
/* 禁止(0)或允許(1)LIFO 方式向?qū)α邪l(fā)送消息*/
#define EN_OS_Q_INT_POST 0
/* 禁止(0)或允許(1)中斷中FIFO 方式相對列發(fā)送消息*/
#define EN_OS_Q_INT_POST_FRONT 1
/* 禁止(0)或允許(1)中斷中LIFO 方式相對列發(fā)送消息*/
#define EN_OS_Q_NMsgs 1
/* 禁止(0)或允許(1)取得隊列中消息數(shù)*/
#define EN_OS_Q_SIZE 0
/* 禁止(0)或允許(1)取得隊列總?cè)萘?/
#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
/* 最大信號量數(shù)目*/
#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)中斷中發(fā)送信號量*/
#define EN_OS_SEM_POST 1
/* 禁止(0)或允許(1)中發(fā)送信號量*/
#define EN_OS_SEM_QUERY 0
/* 禁止(0)或允許(1)查詢信號量*/
#if EN_TIMER_SHARING == 0
#define TIME_ISR_TASK_ID SHOW_TASK_ID
/* 定義系統(tǒng)定時器軟中斷觸發(fā)的任務(wù)ID*/
#endif
#ifdef IN_OS_CPU_C
#if EN_USER_TICK_TIMER > 0
extern void UserTickTimer(void);
/* 系統(tǒng)定時中斷中調(diào)用的用戶函數(shù)*/
#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 位整數(shù)關(guān)鍵字*/
typedef signed char int8;
/* 定義可移植的有符號8 位整數(shù)關(guān)鍵字*/
typedef unsigned int uint16;
/* 定義可移植的無符號16 位整數(shù)關(guān)鍵字*/
typedef signed int int16;
/* 定義可移植的有符號16 位整數(shù)關(guān)鍵字*/
typedef unsigned long uint32;
/* 定義可移植的無符號32 位整數(shù)關(guān)鍵字*/
typedef signed long int32;
/* 定義可移植的有符號32 位整數(shù)關(guān)鍵字*/
#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 的高位字節(jié)*/
#define LOW_BYTE 1 /* uint16 的低位字節(jié)*/
#define OS_TASK_SW() OSCtxSw() /* 任務(wù)切換函數(shù)*/
#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
/*系統(tǒng)定時器使用的中斷*/
#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
*************************************************************/
/**********************************/
/* "以下為系統(tǒng)配置" */
/**********************************/
#pragma REGPARMS
#include
#include
#include
#define const code
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/**********************************/
/* "操作系統(tǒng)定義" */
/**********************************/
#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"
/**********************************/
/* "以下為程序配置" */
/**********************************/
//任務(wù)定義
#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 };
//函數(shù)數(shù)組TaskFuction[]保存了各個任務(wù)初始PC 指針,其按任務(wù)ID 順序保存
#endif
/**********************end***********************************/
ZLG7290 應(yīng)用函數(shù)程序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
/*************************************************************
** 函數(shù)名稱: DelayNS
** 功能描述: 長軟件延時
** 輸 入: I : 延時參數(shù),值越大時延時越久
** 輸 出: 無
** 全局變量: 無
** 調(diào)用模塊: 無
*************************************************************/
void delayMS(unsigned char i)
{
unsigned char j,k;
for(k=0;kfor(j=0;j<60;j++);
}
/*************************************************************
** 函數(shù)名稱: ZLG7290_SendData
** 功能描述: 發(fā)送數(shù)據(jù)
** 輸 入: SubAdd : 輸入數(shù)據(jù)
** DATA : 輸入值
**
** 輸 出: 0 : Fail
** 1 : OK
** 全局變量: 無
** 調(diào)用模塊: 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;
}
/*************************************************************
** 函數(shù)名稱: ZLG7290_SendCmd
** 功能描述: 發(fā)送命令(對子地址7、8)
** 輸 入: DATA1 : 命令1
** DATA2 : 命令2
**
** 輸 出: 0 : Fail
** 1 : OK
** 全局變量: 無
** 調(diào)用模塊: 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;
}
/*************************************************************
** 函數(shù)名稱: ZLG7290_SendBuf
** 功能描述: 向顯示緩沖區(qū)發(fā)送數(shù)據(jù)
** 輸 入: * disp_buf : 要發(fā)送的數(shù)據(jù)的起始地址
** num : 發(fā)送個數(shù)
**
** 輸 出: 無
** 全局變量: 無
** 調(diào)用模塊: 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++;
}
}
/*************************************************************
** 函數(shù)名稱: ZLG7290_SendBuf1
** 功能描述: 向顯示緩沖區(qū)發(fā)送非譯碼數(shù)據(jù)
** 輸 入: * disp_buf : 要發(fā)送數(shù)據(jù)的起始地址
** num : 發(fā)送字節(jié)個數(shù)
**
** 輸 出: 無
** 全局變量: 無
** 調(diào)用模塊: ISendStr
*************************************************************/
void ZLG7290_SendBuf1(unsigned char * disp_buf,unsigned char num)
{
ISendStr(zlg7290,0x10,disp_buf,num);
}
/*************************************************************
** 函數(shù)名稱: ZLG7290_GetKey
** 功能描述: 讀取鍵值
** 輸 入: 無
**
** 輸 出: >0 鍵值
** =0 無鍵按下
** 全局變量: 無
** 調(diào)用模塊: 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();
}
/*鍵盤中斷服務(wù)函數(shù)*/
void int_ex1() interrupt 0
{
OS_INT_ENTER();
OS_ENTER_CRITICAL();
key=ZLG7290_GetKey(); //讀取鍵值
OS_EXIT_CRITICAL();
OSIntExit();
}
/*顯示任務(wù)*/
void TaskA(void)
{
while (1)
{
OS_ENTER_CRITICAL();
DISPLAY(disp_buf); /*顯示*/
OS_EXIT_CRITICAL();
OSWait(K_TMO,1);
}
}
/*8 的移動和產(chǎn)生任務(wù)*/
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);
}
}
/*接收按鍵任務(wù)*/
void TaskC(void)
{
uint8 x=0XFF;
while (1)
{
x=key;
if(x==0x07) /*如果有鍵值鍵入就發(fā)出發(fā)彈命令*/
{
x=0xff;
key=0xff;
OSSemPost(0);
}
OSWait(K_TMO,1);
}
}
/*發(fā)子彈任務(wù)*/
void TaskD(void)
{
uint8 y;
while (1)
{
if(OSSemPend(0,0)==OS_SEM_OK) /*接收到發(fā)彈信號*/
{
OS_ENTER_CRITICAL();
disp_buf[7]=0x0a; /*發(fā)彈*/
for(y=0;y<7;y++)
if(disp_buf[y]==0x0a)
disp_buf[7]=0x0f;
OS_EXIT_CRITICAL();
}
OSWait(K_TMO,10);
}
}
/*子彈飛行任務(wù)*/
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);
}
}
/*中彈處理任務(wù)*/
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);
}
}
/*顯示函數(shù),由于該函數(shù)為不可重入函數(shù),所以調(diào)用前先關(guān)中斷*/
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://ttokpm.com/soft/6/2008/200806264386.html
評論
查看更多