谢谢!我倒是觉得是不是写得不够清楚明白或是组织得不好,好吧,我语文是体育老师都教的。那再把调度器所有内容贴出来:
首先是“sch_cfg.h”- #ifndef __SCH_CFG_H
- #define __SCH_CFG_H
- #include "stm8s.h"
- //定义数据类型
- typedef unsigned char SCH_UINT8;
- typedef unsigned int SCH_UINT16;
- //调度器节拍与硬件系统定时器相关定义
- #define SCH_SYS_TICKS_MS 1 //定义调度系统时钟节拍时间(ms),无特殊情况不建议更改此项
- #define SCH_HW_TIM_MS 0.1 //硬件定时器中断(溢出)周期(ms),此项根据实际系统调整
- #define SCH_TIM_TO_TICKS_CMP (SCH_UINT8)(SCH_SYS_TICKS_MS/SCH_HW_TIM_MS) //硬件定时器到系统节拍计数比较值
- //定义可裁剪部分
- #define SCH_CFG_Q_EN 1u /* 任务内建消息使能 */
- #endif //__SCH_CFG_H
[color=rgb(51, 102, 153) !important]复制代码
然后是“schedule.h”- #ifndef __SCHEDULE_H
- #define __SCHEDULE_H
- #include "sch_cfg.h"
- //U16延时节拍不能大于65534,即任务最大延时时间65534*SCH_SYS_TICKS_MS(1ms)=65.534S
- #define SCH_DLY_TYPE SCH_UINT16
- #define SCH_MAX_TASKS 255 //任务数量,最大为255个。
- #if SCH_MAX_TASKS <= 255
- #define SCH_MAX_TASK_TYPE SCH_UINT8 //最大任务数<=255时定义为u8
- #else
- #define SCH_MAX_TASK_TYPE SCH_UINT16 //最大任务为>255则定义为u16
- #endif
- #define SCH_TASK_RUN 0
- #define SCH_TASK_PEND (SCH_DLY_TYPE)0xffff
- #define SCH_CURR_LINE (SCH_UINT8)(__LINE__+(!__LINE__)) //定义当前行号的具体实现
- #define SCHTaskBegin() static SCH_UINT8 SchLc=0; switch(SchLc){ case 0://跳转开始,中间可插入延时,调用子函数;(适用主/子函数)
- #define SCHTaskEnd() ;}; SchLc=0; //跳转结束
- struct SchTcb
- {
- #if SCH_CFG_Q_EN > 0u
- void *pData; //消息指针
- SCH_UINT8 Size; //消息的大小
- #endif
- SCH_DLY_TYPE TimeCounter; //定时计数器,时基为 "SCH_SYS_TICKS_MS"
- void (*pTask)(); //任务指针
- struct SchTcb *pNextTCB; //下一个任务控制块指针
- };
- typedef struct SchTcb SCH_TCB;
- //-----------------------------------操作作当前任务及调用子任务------------------------------------------
- //挂起(暂停)当前任务,即任务自身
- #define SCHCurTaskPend() {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=SCH_TASK_PEND;}return;case SCH_CURR_LINE:
- //当前任务延时X个时间节拍后恢复
- #define SCHCurTaskDly(Ticks) {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=Ticks;}return ;case SCH_CURR_LINE:
- //任务内调用子任务
- #define SCHTaskCallSub(SubTaskName)
- {
- {SchLc=SCH_CURR_LINE;;pCurTCB->TimeCounter=SCH_TASK_RUN;}return;case SCH_CURR_LINE:
- SubTaskName();
- if (pCurTCB->TimeCounter != SCH_TASK_RUN)
- return ;
- }
- //----------------------------------------消息-------------------------------------------
- #if SCH_CFG_Q_EN > 0u
- #define SCH_Q_FREE 1
- #define SCH_Q_BUSY 0
- //等待消息
- #define SCHTaskQpend() {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=SCH_TASK_PEND;pCurTCB->pData=(void *)0;}return;case SCH_CURR_LINE:
- //释放消息
- extern void SCHTaskQpost(SCH_TCB *pPostTCB,
- void *pData,
- SCH_UINT8 Size);
- //获取消息队列状态
- extern SCH_UINT8 SCHTaskGetQFree(SCH_TCB *pTaskTCB);
- #endif
- extern SCH_UINT8 g_u8SchedTicksCnt;
- extern SCH_TCB *pCurTCB;
- //extern void SCHTaskPend(SCH_TCB *pTaskPendTCB); //不常用的功能,须要时可去除注释
- //extern void SCHTaskResume(SCH_TCB *pTaskTCB);
- //extern void SCHTaskDly(SCH_TCB *pTaskDlyTCB, SCH_DLY_TYPE Ticks);
- extern void SCHTimeTick(void);
- extern void SCHTaskSchedStart();
- extern void SCHTaskCreate( SCH_TCB *pNewTCB,
- void (*pNewTask)());
- #endif //__SCHEDULE_H
[color=rgb(51, 102, 153) !important]复制代码
最后是“schedule.c”- #include "schedule.h"
- SCH_TCB *pFirstTCB, *pCurTCB;
- static SCH_MAX_TASK_TYPE TaskNumberSum = 0;
- SCH_UINT8 g_u8SchedTicksCnt = 0;
- /* 任务节拍处理 */
- void SCHTimeTick(void)
- {
- SCH_MAX_TASK_TYPE i;
- SCH_TCB *pTCB;
- if (g_u8SchedTicksCnt >= SCH_TIM_TO_TICKS_CMP)
- {
- g_u8SchedTicksCnt -= SCH_TIM_TO_TICKS_CMP;
- pTCB = pFirstTCB;
- for (i = 0; i < TaskNumberSum; i++)
- {
- if ((pTCB->TimeCounter != SCH_TASK_PEND)
- && (pTCB->TimeCounter > 0))
- {
- pTCB->TimeCounter--;
- }
- pTCB = pTCB->pNextTCB;
- }
- }
- }
- /* 任务创建,调试时可在任务创建失败处放置断点 */
- void SCHTaskCreate(SCH_TCB *pNewTCB,
- void (*pNewTask)(void))
- {
- if (TaskNumberSum == 0)
- {
- pFirstTCB = pNewTCB; //备份第一个任务控制块地址
- pNewTCB->pTask = pNewTask; //新创建的任务控制块的函数指针指向新创建的任务
- pCurTCB = pNewTCB; //最新任务控制块地址给当前任务控制块指针
- pCurTCB->pNextTCB = pCurTCB; //因为只有一个任务,所以指令的下一个任务控制块地址就是自己
- }
- else if (TaskNumberSum < SCH_MAX_TASKS)
- {
- pNewTCB->pTask = pNewTask; //新创建的任务控制块的函数指针指向新创建的任务
- pNewTCB->pNextTCB = pCurTCB->pNextTCB; //当前任务控制块指向的下一个任务控制块由新建的任务控制块来指向
- pCurTCB->pNextTCB = pNewTCB; //当前任务控制块指向的下一个任务控制块更新为新建的任务
- pCurTCB = pNewTCB; //新建的任务控制块更新为当前任务控制块
- }
- else
- {
- TaskNumberSum--; //任务创建失败,调试时可在此放置断点
- }
- TaskNumberSum++;
- #if SCH_CFG_Q_EN > 0u
- pNewTCB->pData = (void *)0;
- pNewTCB->Size = 0;
- #endif
- }
- void SCHTaskSchedStart(void)
- {
- SCHED_SART:
- pCurTCB = pFirstTCB; //指向第一个创建的任务,之后按创建时的顺序执行下去
- while (1)
- {
- SCHTimeTick(); //如果任务Tick满足条件,则将其置于可执行状态
- if (SCH_TASK_RUN == pCurTCB->TimeCounter) //任务处于可执行状态
- {
- pCurTCB->TimeCounter = SCH_TASK_PEND; //设置为挂起状态,保证任务只执行一次
- pCurTCB->pTask(); //执行当前任务控制块指向的任务
- goto SCHED_SART; //每执行完一个任务,都重新查找一次可执行最高优先级任务
- }
- pCurTCB = pCurTCB->pNextTCB; //指向下一个任务控制块,查找下个任务是否可执行
- }
- }
- ////----------------------------------操作指定任务,不常用---------------------------------------------------
- ////操作当前任务及调用子任务在"schedule.h"中
- //
- ////挂起(暂停)指定任务
- //void SCHTaskPend(SCH_TCB *pTaskPendTCB)
- //{
- // pTaskPendTCB->TimeCounter = SCH_TASK_PEND;
- //}
- //
- ////恢复指定任务(运行)
- //void SCHTaskResume(SCH_TCB *pTaskResumeTCB)
- //{
- // pTaskResumeTCB->TimeCounter = SCH_TASK_RUN;
- //}
- //
- ////指定任务延时X个时间节拍后恢复
- //void SCHTaskDly(SCH_TCB *pTaskDlyTCB, SCH_DLY_TYPE Ticks)
- //{
- // pTaskDlyTCB->TimeCounter = Ticks;
- //}
- //---------------------------------消息-----------------------------------------
- //释放消息
- #if SCH_CFG_Q_EN > 0u
- void SCHTaskQpost(SCH_TCB *pPostTCB,
- void *pData,
- SCH_UINT8 Size)
- {
- pPostTCB->pData = pData;
- pPostTCB->Size = Size;
- pPostTCB->TimeCounter = SCH_TASK_RUN;
- }
- //查询消息列队状态,是否是自由(可用)或忙(不可用),调用SCHTaskQpend()时会将其设置为自由状态
- SCH_UINT8 SCHTaskGetQFree(SCH_TCB *pTaskTCB)
- {
- if (pTaskTCB->pData == ((void *)0))
- {
- return SCH_Q_FREE;
- }
- else
- {
- return SCH_Q_BUSY;
- }
- }
- #endif
[color=rgb(51, 102, 153) !important]复制代码
参考了不少本论坛的帖子,已经记不清具体是哪些了……
|