关于裸机多任务
// 任务结构typedef struct _TASK_COMPONENTS{ uint8 Run; // 程序运行标记:0-不运行,1运行 uint8 Timer; // 计时器 uint8 ItvTime; // 任务运行间隔时间 void (*TaskHook)(void); // 要运行的任务函数} TASK_COMPONENTS; // 任务定义//定时器中断函数
void TaskRemarks(void){ uint8 i; for (i=0; i<TASKS_MAX; i++) // 逐个任务时间处理 { if (TaskComps[i].Timer) // 时间不为0 { TaskComps[i].Timer--; // 减去一个节拍 if (TaskComps[i].Timer == 0) // 时间减完了 { TaskComps[i].Timer = TaskComps[i].ItvTime; // 恢复计时器值,从新下一次 TaskComps[i].Run = 1; // 任务可以运行 } } }}/*************************************************************************************** FunctionName : TaskProcess()* Description : 任务处理* EntryParameter : None* ReturnValue : None**************************************************************************************/void TaskProcess(void){ uint8 i; for (i=0; i<TASKS_MAX; i++) // 逐个任务时间处理 { if (TaskComps[i].Run) // 时间不为0 { TaskComps[i].TaskHook(); // 运行任务 TaskComps[i].Run = 0; // 标志清0 } } }static TASK_COMPONENTS TaskComps[] = { {0, 60, 60, TaskDisplayClock}, // 显示时钟 {0, 20, 20, TaskKeySan}, // 按键扫描 {0, 30, 30, TaskDispStatus}, // 显示工作状态 // 这里添加你的任务。。。。};这个就要靠你自己编码了 ,既然在滴答中断中做任务调度,那么只需在延时的滴答时间内不去做该任务的调度即可,这样不就是实现了延时挂起任务了吗 做一个实现延时并且挂起任务的函数api
刚才找到了那个案例,看了下还真是大循环……并不适合我现在做的这个多任务并行产品上,会考虑用OS去解决这个问题……
不过就是心理有疑问:不用OS能不能很好的解决这些问题呢?又不用额外开个定时器呢?
之前裸跑做复杂应用的时候难道都是像mini的综合历程一样很费劲的写菜单数据结构再来个大循环?要真是这样上OS确实是上上之策
总想把不懂得东西搞清楚……有时候太爱钻牛角尖,自己跟自己过不去
不过就是心理有疑问:不用OS能不能很好的解决这些问题呢?又不用额外开个定时器呢?
之前裸跑做复杂应用的时候难道都是像mini的综合历程一样很费劲的写菜单数据结构再来个大循环?要真是这样上OS确实是上上之策
总想把不懂得东西搞清楚……有时候太爱钻牛角尖,自己跟自己过不去
都说ucos商业要钱,freertos不要钱……那么ucos怎么知道我在产品上用没用他的系统呢?
“小的延时通过死等实现,对于大于最小时间片(1ms)的延时,是不是在delay的地方重新对TaskComps.Timer进行赋值呢?”
这个问题是你提出来的吧?别的不说,先考虑IIC时序,有部分延时是超过1ms的,那请问你怎么解决这个时序的延时?想不通的话看看我上面的截图吧,我的测试代码是最小延时节拍是1ms,只要你的IIC延时大于1ms,可以直接像操作系统那样子调用PROCESS_DELAY来实现
楼主,你贴的代码,是属于时间触发的嵌入式系统构架!
然而,楼主你的理解本质上是错的!
原因:TaskProcess这个函数就不应该在中断里运行,而是应该在主循环运行!
结构是:IRQ:TaskRemarks
Main Loop:TaskProcess
这是典型的前台负责系统滴答,后台负责任务轮询调度!
然后:在设计任务的时候,设计任务时单次运行时间应该越短越好!
除时序延时外的延时都尽量去除而采用状态转移(状态机)来处理!
假如要发送一个hello
如果while(print(hello))这种形式是最笨的设计方法!
用switch ---h---e---l---l---o把hello分成5次发送,发送不要死等标记,发送成功退出,不发送成功照样退出!
设计的时候考虑消费者生产者原则!认清辅助和主线任务,必要的时候要做取舍(偏心)!
然而,楼主你的理解本质上是错的!
原因:TaskProcess这个函数就不应该在中断里运行,而是应该在主循环运行!
结构是:IRQ:TaskRemarks
Main Loop:TaskProcess
这是典型的前台负责系统滴答,后台负责任务轮询调度!
然后:在设计任务的时候,设计任务时单次运行时间应该越短越好!
除时序延时外的延时都尽量去除而采用状态转移(状态机)来处理!
假如要发送一个hello
如果while(print(hello))这种形式是最笨的设计方法!
用switch ---h---e---l---l---o把hello分成5次发送,发送不要死等标记,发送成功退出,不发送成功照样退出!
设计的时候考虑消费者生产者原则!认清辅助和主线任务,必要的时候要做取舍(偏心)!
出问题那是设计者笨!
任务的运行期间出现中断是必然的事情,这个时候就需要你来保护了(原子保护)
这个正点原子保护在你们用的OS中有个名词,叫临界区!

浙公网安备 33010602011771号