|
回复: 急用的,谁能帮我写下这个程序
用一个软件调度器:
// **建立任务队列**
SCH_Add_Task(FLASH_LED1, 200, 200); /*设系统时标为5个毫秒*/
SCH_Add_Task(FLASH_LED2, 200*2, 200);
SCH_Add_Task(FLASH_LED3, 200*3, 200);
给你软件内核:
A. 头文件:
/*-------------------------------------------------------*-
SCH51.H (V1.1)
调度器的数据结构以及任务队列
-*-------------------------------------------------------*/
/*
* Copyright (c) 2006,wsl
* All rights reserved
*
* 文件名称: SCH51.H
* 文件标识:
* 摘 要: 调度器的核心是调度器的数据结构.这是一种用户
* 自定义的数据类型,集中了每个任务所需的信息.
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
*********************************************************/
#ifndef _SCH51_H
#define _SCH51_H
#include"Main.H"
//---------------公用数据类型声明------------------------
// 可能的话,存储在DATA区,以供快速存取
// 每个任务的存储器总和是7个字节
typedef data struct
{
// 指向任务的指针(必须是一个'void(void)'函数)
// 构造一个指向函数的指针变量.专门用来存放函数的入口地址
void (code *pTask)(void);
// 延迟Delay个时标后函数将第一次运行
// 当Delay=0时,任务立即运行
unsigned int Delay;
// 在连续的运行之间的间隔(时标)
// 当Period=0时,任务运行一次.
unsigned int Period;
// 当任务需要运行时(由调度器)加1
unsigned char RunMe;
} sTask;
//------------公用的函数原型----------------------------
// 调度器内核函数
extern void SCH_Dispatch_Tasks(void);
extern unsigned char SCH_Add_Task(void (code *pFunction)(), // 任务指针
const unsigned int DELAY, // 延迟Delay个时标后函数将第一次运行
const unsigned int PERIOD); // 连续的运行之间的间隔(时标)
extern bit SCH_Delete_Task(const unsigned char TASK_INDEX);
extern void SCH_Init_Timer2(void);
extern void SCH_Start(void);
//--------------------------------------------------------
#endif
//-------------------END OF FILE-------------------------
B.c文件:
/*--------------------------------------------------------------------*-
SCH51.C (V1.00)
这里是调度器的内核函数,这个函数可以用于所有的8051芯片.
--- SCH_MAX_TASKS必须由用户设置 ----
-*---------------------------------------------------------------------*/
/*
* Copyright (c) 2006
* All rights reserved
*
* 文件名称: SCH51.C
* 文件标识:
* 摘 要: 内核函数
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
************************************************************************/
#include"main.H"
#include"Port.H"
#include"SCH51.H"
#include "MMI.h"
#include"Uart.h"
#include"LedDisp.h"
/*私有函数*/
static void SCH_Updata(void);
static void SCH_Report_Status(void);
//---------------公用常数-------------------------------
// 在任一时刻要求的任务最大数目
// 每个新建项目都必须调整
#define SCH_MAX_TASKS (8)
//-------公用变量定义-----------------------------------------------------
// 任务队列
sTask SCH_tasks_G[SCH_MAX_TASKS];
#define RETURN_NORMAL (bit)0
#define RETURN_ERROR (bit)1
// 错误代码
#define ERROR_SCH_TOO_MANY_TASKS (1)
#define ERROR_SCH_CANNOT_DELETE_TASK (2)
// 用来显示错误代码
static unsigned char Error_code_G = 0;
static unsigned char RTCCounter = 0;
/*---------------------------------------------------------*-
* 函数名称: SCH_Update_Server()
* 入 口:
* 出 口:
* 函数功能: 调度器的中断服务程序
*
* 说 明: "刷新"函数,确定某个任务需要运行时,将这个任务的
* RunMe标志加1,然后该任务将由调度程序执行.
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
void SCH_Update_Server(void)interrupt 5
{
TF2 = 0; // 必须手工清除
if(++RTCCounter == 200)
{
RTCCounter = 0;
RTC_Soft_clock(); /*定时器例行程序*/
/*每秒钟查询一次是否有闹铃时间到*/
if (RingIDRegister > 0)
{ /*响铃*/
Ring_server();
}
}
FlashFreq();
SCH_Updata();
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Dispatch_Tasks()
* 入 口:
* 出 口:
* 函数功能: 调度函数,当一个任务()需要运行时,此函数将运行它,
*
* 说 明: 这个函数必须被主循环(重复)调用
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
void SCH_Dispatch_Tasks(void)
{
unsigned char Index;
// 调度(运行)下一个任务(如果有任务就绪)
for (Index=0; Index<SCH_MAX_TASKS; Index++)
{
if (SCH_tasks_G[Index].RunMe > 0)
{
// 运行任务
(*SCH_tasks_G[Index].pTask)();
// 复位 / 降低RunMe标志
SCH_tasks_G[Index].RunMe -= 1;
// 周期性的任务将自动地再次运行
// 如果这个是'单次'任务,将它从队列中删除
if (SCH_tasks_G[Index].Period == 0)
{
SCH_Delete_Task(Index);
}
}
}
// 报告系统状况
SCH_Report_Status();
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Report_Status()
* 入 口:
* 出 口:
* 函数功能: 用来显示错误代码
*
* 说 明: 错误只在有限的时间内显示,此后错误代码被复位为0.
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
void SCH_Report_Status(void)
{
// 只在需要报告错误时适用
// 检查新的错误代码
if (Error_code_G != 0)
{
switch (Error_code_G)
{
case 1: uart_send_string("Tasks Full\n", 0); break; // 任务队列已满
case 2: uart_send_string("No Tasks\n", 0); break; // 这里没有任务
default: break;
}
}
Error_code_G = 0; // 复位错误代码
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Add_Task()
* 入 口: (*pFunction)任务指针,(DELAY)到第一次运行间隔时标,
* (PERIOD)每次运行的间隔时标
*
* 出 口: 返回SCH_MAX_TASKS表示任务队列已满
* 返回(Index)=任务位置
*
* 函数功能: 用来添加任务到任务队列上,以保证它们在需要的时
* 候被调用
*
* 说 明: 使任务函数每隔一定间隔或在用户的延迟之后执行.
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
unsigned char SCH_Add_Task(void (code *pFunction)(), // 任务指针
const unsigned int DELAY, // 延迟Delay个时标后函数将第一次运行
const unsigned int PERIOD) // 连续的运行之间的间隔(时标)
{
unsigned char Index = 0;
// 首先在队列中找到一个空隙(如果有的话)
while ((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))
{
Index++; // 如果没有,就在队列中一下位置检索
}
// 是否已经到达队列的结尾?
if (Index == SCH_MAX_TASKS)
{
// 任务队列已满
// 设置全局错误变量
Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
// 同时返回错误代码
return SCH_MAX_TASKS;
}
// 如果能运行到这里,则说明任务队列中有空间
SCH_tasks_G[Index].pTask = pFunction;
SCH_tasks_G[Index].Delay = DELAY;
SCH_tasks_G[Index].Period = PERIOD;
SCH_tasks_G[Index].RunMe = 0;
// 返回任务的位置(以便以后删除)
return Index;
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Delete_Task()
* 入 口: TASK_INDEX -任务索引.由SCH_Add_task()提供
*
* 出 口: 返回值: RETURN_ERROR(或)RETURN_NORMAL
*
* 函数功能: 从调度器删除任务.
*
* 说 明: 请注意:并不是从存储器中删除相关的函数,仅仅是不再
* 由调度器调用这个任务.
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
bit SCH_Delete_Task(const unsigned char TASK_INDEX)
{
bit Return_code;
if (SCH_tasks_G[TASK_INDEX].pTask == 0)
{
// 这里没有任务
// 设置全局错误变量
Error_code_G = ERROR_SCH_CANNOT_DELETE_TASK;
// 同时返回错误代码
Return_code = RETURN_ERROR;
}
else
{
Return_code = RETURN_NORMAL;
}
// 删除任务
SCH_tasks_G[TASK_INDEX].pTask = 0x00;
SCH_tasks_G[TASK_INDEX].Delay = 0;
SCH_tasks_G[TASK_INDEX].Period = 0;
SCH_tasks_G[TASK_INDEX].RunMe = 0;
// 返回状态
return Return_code;
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Update()
* 入 口:
* 出 口:
* 函数功能: 在调度器的中断服务程序中运行
*
* 说 明: "刷新"函数,确定某个任务需要运行时,将这个任务的
* RunMe标志加1,然后该任务将由调度程序执行.
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
void SCH_Updata(void)
{
unsigned char Index;
// 注意: 计算单位为"时标" (不是毫秒)
for (Index=0; Index < SCH_MAX_TASKS; Index++)
{
// 检测这里是否有任务?
if (SCH_tasks_G[Index].pTask != 0)
{
if (SCH_tasks_G[Index].Delay == 0)
{
// 任务需要运行
SCH_tasks_G[Index].RunMe += 1; // RunMer标志加1
if (SCH_tasks_G[Index].Period != 0)
{
// 调度定期的任务再次运行
SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
}
}
else
{
// 还没有准备好运行,延迟减1
SCH_tasks_G[Index].Delay -= 1;
}
}
}
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Init_Timer2()
* 入 口:
* 出 口:
* 函数功能: 准备调度器数据结构并且设置定时器以所需的频率中断
*
* 说 明: 调度器初始化化函数,必须在使用调度器之前调用它
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
void SCH_Init_Timer2(void)
{
unsigned char i;
for (i=0; i<SCH_MAX_TASKS; i++)
{
SCH_Delete_Task(i);
}
// 复位全局错误变量
// - SCH_Delete_Task()将产生一个错误代码
// (因为任务队列是空的)
// Error_code_G = 0;
// 设置定时器2
// 16位定时自动重装
T2CON = 0x04;
TH2 = PRELOAD_05mS_H;
RCAP2H = PRELOAD_05mS_H;
TL2 = PRELOAD_05mS_L;
RCAP2L = PRELOAD_05mS_L;
ET2 = 1; // 使能定时器2中断
TR2 = 1; // 启动定时器2
}
/*---------------------------------------------------------*-
* 函数名称: SCH_Start()
* 入 口:
* 出 口:
* 函数功能: 通过允许中断来启动调度器
*
* 说 明: 在添加了所有定期的任务之后调用,从而使任务保持同步.
* 注意:应该只使能调度器中断
*
* 当前版本: 1.1 * 取代版本:
* 作 者: wsl * 原作者 : Michael J.Pont
* 完成日期: 2006-09-14 * 完成日期:
-*---------------------------------------------------------*/
void SCH_Start(void)
{
EA = 1;
}
//**************END OF FILE*********************************
看明白了我想你一定能完成上面的那个任务. |
|