在许多的单片机项目中,因为操作体系的体积以及运用的布景常识,假如选用的话,可能让项目脱离首要事务方向,这个时分很有必要运用简略的协程多使命。
1协程多使命的特色
每个使命优先级相等
每个使命自动开释CPU控制权
2 UCOS等操作体系的特色
使命存在不同优先级,很便利进行CPU资源的分配。
关于ucos的使命来说,每个使命都以为自己是独占cpu的,能够随意休眠之类,这样关于代码的风格的约束比较小,比较好修正现存的模块。
操作体系一般供给比较多的服务,关于杂乱运用比较好。
3 协程多使命的运用场合
协程办法合适简略的多使命,每个使命要承认其契合协程的模型,不能堵塞cpu运转,要自动开释CPU,假如考虑到多人协作,或许引进第三方的代码,进来,那么协程办法恐怕作业量过大(模型改造查看),这时最好运用操作体系。
协程或许操作体系的渠道的树立,这些都需求堆集,也没有什么高档和初级的差异,仅仅针对不同的场景和开发人员挑选不同罢了。
4协程多使命的完结
为了运用便利,并且将来便于体系升级,多使命选用依据接口的办法界说和完结。
4.1 使命的界说
每个使命会办理自己的数据,供给对外接口,每个使命供给以下方法结构
Struct _task1
{
//使命对外接口,函数指针
Void (*start)(Struct _task1*handle);
Void (*run)(Struct _task1*handle);
Void (*stop)(Struct _task1*handle);
//其他对外接口
…
//使命私有数据
} task1;
之所以将对外接口放在使命结构体中,是为了着重这些是使命的对外接口,并且客户只能调用这儿面的接口,别的函数指针也很便利的供给了一个接口和完结的分隔层
4.2 使命的完结
使命的完结层面,用户能够依据对体系和事务的了解,做体系演化,而不会影响到外部接口的运用
//使命接口完结函数
Void task1_start(Struct _task1*handle)
{
//设置使命开端标识
}
Void task1_run(Struct _task1*handle)
{
If(handle->status1)
{
//处理
}
Else if(handle->status2)
{
//处理
}
}
Void task1_stop(Struct _task1*handle)
{
//设置使命完毕标识
}
//使命初始化函数,结构使命结构体
Void task1_init(Struct _task1*handle)
{
Handle->start = task_start;
Handle->run = task_run;
Handle->stop= task_stop;
}
4.3 调用方法
4.3.1 界说大局使命结构体
Struct _task1
{
//使命对外接口,函数指针
Void (*start)(Struct _task1*handle);
Void (*run)(Struct _task1*handle);
Void (*stop)(Struct _task1*handle);
//其他对外接口
…
//使命私有数据
} task1;
4.3.2 使命初始化
Task1_init(&task1);
4.3.3 开端使命
Task1->start(&task1);
4.3.4 完毕使命
Task1->stop(&task1);
4.3.5 使命运转
一般体系在发动后运转的一个无限循环句子中有
While(1)
{
Task1->run(&task1);
Task2->run(&task2)
…其他使命运转
}
5 定时器以及延时的完结办法
协程多使命不会在代码中运用sleep()堵塞CPU的办法做定时器或许休眠,定时器会有一个独自的使命,使命供给新增定时器、删去定时器、查询定时器值等接口来供给软件定时器功用。
6 使命间通讯
原则上经过使命供给的接口来通讯,当然假如通讯作业量过大,不对立运用第三方使命来完结通讯。
7 驱动层模块使命比如
关于单片机协程多任务来说,运用层和驱动层是优先级相同的使命,关于许多的驱动来说,例如UART驱动,其发送和接纳许多选用的是查询的办法来进行,下面简略的运用多使命的结构办法来阐明驱动的写作
Struct _com{
//使命对外接口,函数指针
Void (*start)(Struct _com*handle);
Void (*run)(Struct _com*handle);
Void (*stop)(Struct _com*handle);
//其他对外接口
Void read(char* ch)
Void write(char* ch)
…
//使命私有数据
//驱动状况,
Char status;
}com1;
//运转代码
Void Com_run(Struct _com * handle)
{
If(read)
{
If(register1)
{
}
Else if(register2)
{
}
}
Else if(write)
{
If(register3)
{
}
Else if(register4)
{
}
}
}
从上面代码可见,驱动模块其实和一般的使命没有差异。