裸机用C语言写多任务程序的时候,用时间片轮询的方式的话,任务里面的延时函数怎么处理呢?

2019-07-19 20:40发布

本帖最后由 小小速 于 2016-11-21 16:48 编辑

最近遇到点麻烦,写了十几天的驱动才发现放在一起主程序没法工作了刚毕业的小白,身边也没个懂的,只能来求助广大网友了
想用时间片轮询的方式,看了一天的资料现在有点迷糊了

[mw_shl_code=c,true]// 任务结构
typedef struct _TASK_COMPONENTS
{
    uint8 Run;                 // 程序运行标记:0-不运行,1运行
    uint8 Timer;              // 计时器
    uint8 ItvTime;              // 任务运行间隔时间
    void (*TaskHook)(void);    // 要运行的任务函数
} TASK_COMPONENTS;       // 任务定义[/mw_shl_code]
定时器中断函数
[mw_shl_code=c,true]void TaskRemarks(void)
{
    uint8 i;
    for (i=0; i<TASKS_MAX; i++)          // 逐个任务时间处理
    {
         if (TaskComps.Timer)          // 时间不为0
        {
            TaskComps.Timer--;         // 减去一个节拍
            if (TaskComps.Timer == 0)       // 时间减完了
            {
                 TaskComps.Timer = TaskComps.ItvTime;       // 恢复计时器值,从新下一次
                 TaskComps.Run = 1;           // 任务可以运行
            }
        }
   }
}[/mw_shl_code]

[mw_shl_code=c,true]/**************************************************************************************
* FunctionName   : TaskProcess()
* Description    : 任务处理
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void TaskProcess(void)
{
    uint8 i;
    for (i=0; i<TASKS_MAX; i++)           // 逐个任务时间处理
    {
         if (TaskComps.Run)           // 时间不为0
        {
             TaskComps.TaskHook();         // 运行任务
             TaskComps.Run = 0;          // 标志清0
        }
    }   
}[/mw_shl_code]
问题在下面这里:
[mw_shl_code=c,true]static TASK_COMPONENTS TaskComps[] =
{
    {0, 60, 60, TaskDisplayClock},            // 显示时钟
    {0, 20, 20, TaskKeySan},               // 按键扫描
    {0, 30, 30, TaskDispStatus},            // 显示工作状态
     // 这里添加你的任务。。。。
};[/mw_shl_code]
时间片轮询去执行任务,每个任务的执行周期是在上面结构体里初始化的,然后每隔一定时间(如1ms)进入定时器中断,在中断函数里刷新任务,同时进行调度,这个能看懂
问题是这种方法,只是说明了每个周期性任务如何互不干扰的运行,但是并没有说当一个任务里面包含delay函数时,delay函数的实现,
比如有一个IIC的任务每隔100ms产生一次通信,这个100ms的周期可以在上面的任务结构体里面初始化参数uint8 ItvTime; // 任务运行间隔时间
那IIC的时序延时又该如何实现呢?小的延时通过死等实现,对于大于最小时间片(1ms)的延时,是不是在delay的地方重新对TaskComps.Timer进行赋值呢?
还有就是这个时间轮询好像没有提到状态机的问题,是不是这种轮询不需要任务里面写状态机就能实现多任务并行呢?





友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
32条回答
小小速
1楼-- · 2019-07-21 04:03
正点原子 发表于 2016-11-21 18:37
楼主这种方式,只能每个任务的运行时间必须小于你的调度周期,否则就肯定出问题了。。。

现在找不到太好的裸跑构架,大任务拆分成小的状态,分步执行,算不算个解决办法呢……
记得原子哥老版本mini板有个综合例程就是裸跑的,不过现在资料更新找不到了
正点原子
2楼-- · 2019-07-21 08:34
 精彩回答 2  元偷偷看……
小小速
3楼-- · 2019-07-21 11:26
本帖最后由 小小速 于 2016-11-21 23:33 编辑
正点原子 发表于 2016-11-21 22:07
我们那是大循环。。。
现在都上OS了,建议上OS
你这样做效果不大

刚才找到了那个案例,看了下还真是大循环……并不适合我现在做的这个多任务并行产品上,会考虑用OS去解决这个问题……
不过就是心理有疑问:不用OS能不能很好的解决这些问题呢?又不用额外开个定时器呢?
之前裸跑做复杂应用的时候难道都是像mini的综合历程一样很费劲的写菜单数据结构再来个大循环?要真是这样上OS确实是上上之策
总想把不懂得东西搞清楚……有时候太爱钻牛角尖,自己跟自己过不去
小小速
4楼-- · 2019-07-21 14:33
FreeRTOS 发表于 2016-11-21 22:29
如果延时时间小于定时器中断的时间,那就只能死等或者另外再开个定时器来完成这部分延时
但我看你问的好像 ...

这个图没看懂是啥意思……我的疑惑确实是状态机下的延时问题
小小速
5楼-- · 2019-07-21 19:03
 精彩回答 2  元偷偷看……
FreeRTOS
6楼-- · 2019-07-22 00:53
小小速 发表于 2016-11-21 23:11
这个图没看懂是啥意思……我的疑惑确实是状态机下的延时问题

“小的延时通过死等实现,对于大于最小时间片(1ms)的延时,是不是在delay的地方重新对TaskComps.Timer进行赋值呢?”

这个问题是你提出来的吧?别的不说,先考虑IIC时序,有部分延时是超过1ms的,那请问你怎么解决这个时序的延时?想不通的话看看我上面的截图吧,我的测试代码是最小延时节拍是1ms,只要你的IIC延时大于1ms,可以直接像操作系统那样子调用PROCESS_DELAY来实现

一周热门 更多>