调用系统服务使任务切换时不保存寄存器变量
中断服务执行任务切换时,保存寄存器变量
支持7个任务,支持7级中断嵌套
基于优先级调度,0号任务具有最高优先级
包含K_FLG K_SEM K_MSG K_TMO这几个系统服务,每种类型的系统服务最多提供16个
单片机源程序如下:
- #define _IN_LQ51_C_
- #include "lq51.h"
- #include<reg52.h>
- /******************************************
- / 定义全局变量
- /******************************************/
- unsigned char data lqTaskStack[lqMaxID+1]; /*任务堆栈指针*/
- unsigned char data lqSPtemp; /*记录ID号=当前任务ID+1的堆栈底部*/
- unsigned char data lqTaskTimer[lqMaxID]; /*任务定时器*/
- unsigned char data lqTaskState[lqMaxID]; /*任务状态表*/
- unsigned char data lqRdyTbl; /*就绪表*/
- unsigned char data lqSwitchType; /*任务切换类型,如果通过中断切换任务则在相应位置1,否则置0*/
- unsigned char data lqIntNum; /*进入中断服务子程序后系统把中断号传给这个变量*/
- unsigned char data lqCrt; /*当前正在运行的任务*/
- #if LQ_FLG_EN /*该事件的最高位表示该标志位是否置位,其他位表示等待该标志量的任务,当标志位置位时,所有等待这个标志的任务都被激活*/
- unsigned char data lqFlgData[lqFlgMax]={
- 0,0
- };
- #endif
- #if LQ_SEM_EN /*信号量数据结构*/
- /*一个信号量数据结构包含两个字节,第一个字节为信号量值*/
- unsigned char data lqSemData[lqSemMax*2]={ /*第二个字节为等待这个信号量的任务*/
- 0,0,
- 0,0};
- #endif
- #if LQ_MSG_EN /*消息邮箱数据结构*/
- /*一个消息邮箱数据结构包含两个字节,第一个字节为消息邮箱的消息*/
- unsigned char data lqMsgData[lqMsgMax*2]={ /*第二个字节的最高位表示当前邮箱是否有消息0表示没有1表示有,其他为表示等待这个消息的任务*/
- 0,0,
- 0,0};
- #endif
- const unsigned char code lqMap[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
- /*****************************************
- / 开始函数
- /这个函数必须在0号任务的最开始的部分调用
- / void lqStart(void);
- /*****************************************/
- void lqStart(void)
- {
- char i;
- for(i=0;i<lqMaxID;++i){
- lqTaskTimer[i] = 0;
- lqTaskState[i] = 0;
- }
- lqRdyTbl=0xFF;
- lqSwitchType=0x00;
- EA = 1;
- lqCrt=0;
- }
- #if LQ_DELAY_EN
- /***************************************************
- / 任务延迟一段时间
- / void lqDelay(unsigned char tmo)
- / tmo:延迟时间,如果tmo=0,那么当前任务休眠,永远不会被激活
- /***************************************************/
- void lqDelay(unsigned char tmo)
- {
- EA=0;
- lqRdyTbl &= ~lqMap[lqCrt];
- lqTaskState[lqCrt] |= K_TMO;
- lqTaskTimer[lqCrt] = tmo;
- EA=1;
- lqSche();
- }
- #endif
- #if LQ_FLG_EN
- /**************************************************
- / 等待标志
- / char lqWaitFlg(unsigned char index,unsigned char tmo)
- / index :标志量索引
- / tmo :超时等待时限,如果为0则无限等待
- / 返回值:
- / 标志量有效返回 K_FLG
- / 在规定的时件内标志量未发生返回 K_TMO
- /*************************************************/
- unsigned char lqWaitFlg(unsigned char index,unsigned char tmo)
- {
- EA=0;
- lqTaskState[lqCrt] &= 0xF0;
- lqTaskState[lqCrt]|= index; /*将当前索引值保存到任务状态的低四位,因为函数是不可重入的*/
- if(lqFlgData[index] & 0x80){ /*标志量置位*/
- lqFlgData[index] = 0;
- EA=1;
- return K_FLG;
- }
- lqFlgData[index] |= lqMap[lqCrt];
- lqRdyTbl &= ~lqMap[lqCrt];
- lqTaskState[lqCrt] |= K_FLG;
- if(tmo){
- lqTaskState[lqCrt] |= K_TMO;
- lqTaskTimer[lqCrt] = tmo;
- }
- EA=1;
- lqSche();
- EA=0;
- index = 0x0F & lqTaskState[lqCrt];
- if(lqTaskState[lqCrt] & K_FLG){ /*等待超时返回*/
- lqTaskState[lqCrt] &= ~K_FLG;
- lqTaskState[lqCrt] |= K_TMO; /*超时标记*/
- lqFlgData[index] &= ~lqMap[lqCrt];
- EA=1;
- return K_TMO;
- }
- EA=1;
- return K_FLG;
- }
- /************************************************
- / 中断服务子程序发送标志
- / char lqSendFlgISR(unsigned char index)
- / index :标志量索引
- / 返回值:
- / 1 -- 有更高优先级的任务就绪,需要执行任务切换
- / 0 -- 不需要执行任务切换
- /************************************************/
- char lqSendFlgISR(unsigned char index)
- {
- char i,j;
- EA=0;
- if(lqFlgData[index] & 0x7F){ /*有任务在等待这个标志事件*/
- i=lqMaxID;
- for(j=0;j<lqMaxID;++j){
- if(lqFlgData[index] & lqMap[j]){ /*任务等待这个标志事件*/
- lqTaskState[j] &= ~K_FLG;
- lqTaskState[j] &= ~K_TMO;
- lqTaskTimer[j] = 0;
- lqRdyTbl |= lqMap[j];
- if(j<i){
- i=j;
- }
- }
- }
- lqFlgData[index] = 0;
- if(i<lqCrt){
- EA=1;
- return 1;
- }
- EA=1;
- return 0;
- }
- lqFlgData[index] = 0x80;
- EA=1;
- return 0;
- }
- /********************************************
- / 任务发送标志事件
- / void lqSendFlg(unsigned char index)
- /********************************************/
- void lqSendFlg(unsigned char index)
- {
- if(lqSendFlgISR(index)){
- lqSche();
- }
- }
- #endif
- #if LQ_SEM_EN
- /************************************************
- / 等待一个信号量
- / char lqWaitSem(unsigned char index,unsigned char tmo)
- / index :信号量索引
- / tmo :超时等待时限,如果为0则无限等待
- / 返回值:
- / 信号量有效返回 K_SEM
- / 在规定的时件内信号量未发生返回 K_TMO
- /************************************************/
- unsigned char lqWaitSem(unsigned char index,unsigned char tmo)
- {
- EA=0;
- lqTaskState[lqCrt] &= 0xF0;
- lqTaskState[lqCrt]|= index; /*因为函数不可重,所以存储信号量索引*/
- index *= 2;
- if(lqSemData[index]){
- --lqSemData[index];
- EA=1;
- return K_SEM;
- }
- lqRdyTbl &= ~lqMap[lqCrt];
- lqSemData[index+1] |= lqMap[lqCrt];
- lqTaskState[lqCrt] |= K_SEM;
- if(tmo){
- lqTaskState[lqCrt] |= K_TMO;
- lqTaskTimer[lqCrt] = tmo;
- }
- EA=1;
- lqSche();
- EA=0;
- index = 0x0F & lqTaskState[lqCrt];
- if(lqTaskState[lqCrt] & K_SEM){
- lqTaskState[lqCrt] &= ~K_SEM;
- lqTaskState[lqCrt] |= K_TMO;
- lqSemData[index*2+1] &= ~lqMap[lqCrt];
- EA=1;
- return K_TMO;
- }
- EA=1;
- return K_SEM;
- }
- /*********************************************
- / 中断子程序发送信号量
- / char lqSendSemISR(unsigned char index)
- / index :信号量索引
- / 返回值:
- / 1 -- 有更高优先级的任务就绪,需要执行任务切换
- / 0 -- 不需要执行任务切换
- /*********************************************/
- char lqSendSemISR(unsigned char index)
- {
- char j;
- EA=0;
- index*=2;
- if(lqSemData[index+1]){
- for(j=0;j<lqMaxID;++j){
- if(lqSemData[index+1] & lqMap[j]){
- break;
- }
- }
- lqSemData[index+1] &= ~lqMap[j];
- lqTaskTimer[j] = 0;
- lqTaskState[j] &= ~K_SEM;
- lqTaskState[j] &= ~K_TMO;
- lqRdyTbl |= lqMap[j];
- if(j<lqCrt){
- EA=1;
- return 1;
- }
- EA=1;
- return 0;
- }
- ++lqSemData[index];
- EA=1;
- return 0;
- }
- /************************************************
- / 任务发送信号量
- / void lqSendSem(unsinged char index)
- /***********************************************/
- void lqSendSem(unsigned char index)
- {
- if(lqSendSemISR(index)){
- lqSche();
- }
- }
- #endif
- #if LQ_MSG_EN
- /*********************************************
- / 等待消息邮箱
- / unsigned char lqWaitMsg(unsigned char index,unsigned char tmo)
- / index :邮箱索引
- / tmo :超时等待时限,如果为0则无限等待
- / 邮箱中的值为 0x00~0xFF
- / lqMsgData[2*index+1]的最高为0表示当前没邮件,
- / 否则表示当前有邮件
- / 返回值 :
- / 如果在规定的时间内有消息送到这个邮箱,则返回这个消息
- / 如果在规定的时间内没有消息送到这个邮箱,则返回 MSG_TMO
- / MSG_TMO在lq51.h中有定义,如果 MSG_TMO 所代表的值是消息的一部分,
- / 那么在这个函数返回后建议执行char lqIsTaskTmo(),检查当前任务
- / 是否从超时返回
- /********************************************/
- unsigned char lqWaitMsg(unsigned char index,unsigned char tmo)
- {
- EA=0;
- lqTaskState[lqCrt] &= 0xF0;
- lqTaskState[lqCrt] |= index;
- index *= 2;
- if(lqMsgData[index+1] & 0x80){ /*当前邮箱有邮件*/
- lqMsgData[index+1] &= 0x7F;
- EA=1;
- return lqMsgData[index];
- }
- lqRdyTbl &= ~lqMap[lqCrt];
- lqMsgData[index+1] |= lqMap[lqCrt];
- lqTaskState[lqCrt] |= K_MSG;
- if(tmo){
- lqTaskState[lqCrt] |= K_TMO;
- lqTaskTimer[lqCrt] = tmo;
- }
- EA=1;
- lqSche();
- EA=0;
- index = lqTaskState[lqCrt] & 0x0F;
- index *= 2;
- if(lqTaskState[lqCrt] & K_MSG){
- lqTaskState[lqCrt] &= ~K_MSG;
- lqTaskState[lqCrt] |= K_TMO;
- lqMsgData[index] = MSG_TMO;
- lqMsgData[index+1] &= ~lqMap[lqCrt];
- }
- lqMsgData[index+1] &= 0x7F;
- EA=1;
- return lqMsgData[index];
- }
- /*******************************************
- / char lqIsMsgEmpty(unsigned char index)
- / index :邮箱索引
- / 返回值:
- / 0 -- 邮箱中有消息
- / 1 -- 邮箱中没有消息
- /******************************************/
- #if LQ_CHK_MSG_EN
- char lqIsMsgEmpty(unsigned char index)
- {
- EA=0;
- if(lqMsgData[index*2+1] & 0x80){
- EA=1;
- return 0; /*邮箱不为空,邮箱中有消息*/
- }
- EA=1;
- return 1; /*邮箱为空,邮箱中无消息*/
- }
- #endif
- /*******************************************
- / 中断子程序发送邮件
- / char lqSendMsgISR(unsigned char index,unsigned char Msg)
- / index :邮箱索引
- / Msg :被发送的消息
- / 如果邮箱中已经存在消息,原来的消息不会被覆盖,函数之间返回
- / 返回值:
- / 1 -- 有更高优先级的任务就绪,需要执行任务切换
- / 0 -- 不需要执行任务切换
- /*******************************************/
- char lqSendMsgISR(unsigned char index,unsigned char Msg)
- {
- EA=0;
- index *= 2;
- if(lqMsgData[index+1] & 0x80){
- EA=1;
- return 0; /*邮箱不为空*/
- }
- lqMsgData[index] = Msg;
- ++index;
- lqMsgData[index] |= 0x80;
- if(lqMsgData[index] & 0x7F){ /*有任务在等待这个邮件*/
- for(Msg=0;Msg<lqMaxID;++Msg){
- if(lqMsgData[index] & lqMap[Msg]){
- break;
- }
- }
- lqMsgData[index] &= ~lqMap[Msg];
- lqTaskState[Msg] &= ~K_MSG;
- lqRdyTbl |= lqMap[Msg];
- if(Msg < lqCrt){
- EA=1;
- return 1;
- }
- }
- EA = 1;
- return 0;
- }
- /********************************************
- / 任务发送邮件
- / void lqSendMsg(unsigned char index,unsigned char Msg)
- / index :邮箱索引
- / Msg :被发送的消息
- /*******************************************/
- void lqSendMsg(unsigned char index,unsigned char Msg)
- {
- if(lqSendMsgISR(index,Msg)){
- lqSche();
- }
- }
- #endif
- #if LQ_TASK_TMO_CHK_EN
- /***********************************************
- / 任务超时返回检查
- / char lqIsTaskTmo()
- / 如果当前任务是超时返回,那么任务状态(lqTaskState)的B_TMO位置位,否则该标志位被清零
- / 一般情况下只针对邮箱事件返回后做超时检查
- / 返回值:
- / 1 -- 当前任务是超时返回
- / 0 -- 当前任务不是超时返回
- /************************************************/
- char lqIsTaskTmo()
- {
- if(lqTaskState[lqCrt] & K_TMO){
- return 1;
- }
- return 0;
- }
- #endif
复制代码
所有资料51hei提供下载:
lq51-master.zip
(216.94 KB, 下载次数: 18)
|