通过状态机+时间片可以实现简单的分时处理系统,但是如何划分模块,时间片又应该定多少才是最好的呢?带着这个问题,我网上搜集了资料,找到一个论文,能解答我的疑问。让我对状态机调度设计有了些心得。做了如下摘要。
1 系统任务模块的划分
在单片机系统中, 实现分时多任务机制关键在于合理地将系统的功能分解成各个任务模块, 且任务模块分得越细系统的实时性就越好1 单片机系统由定时器产生系统时间片, 由系统调度程序将时间片分配给各任务模块1 系统任务模块可分为功能模块和实时模块1功能模块是在程序中可独立运行的模块, 如输入、输出、数据处理、显示、键盘扫描、模糊控制系统
中的模糊推理等任务模块1 其特点是模块的内部结构是没有停留的, 每次进入模块只执行模块中的当前时刻的代码部分, 模块内部不存在延时1 在给定时间片内的模块内部也可有子任务模块, 与时间片大小的划分有关1
实时模块是执行实时任务功能的模块, 主要功能是将实时任务转为非实时的消息和数据1 比如串口通信, 接收到数据后, 可只处理必须的数据, 再产生消息, 让通信模块对其处理1系统任务模块的划分与系统功能密切相关, 系统功能分解到任务模块1 系统功能分解即任务模块的划分, 模块划分应注意以下几个问题:
1) 任务模块应保证在系统时间片内执行完毕1在任务模块内尽量不用软件延时1 如在动态显示模块设计中每位显示间要求有(1~ 2) m s 左右的延时来保证显示稳定, 若采用一次将所有位全部显示一遍, 显示模块执行时间将会很长, 可以采用一次只显示一位的方法1 此外也可采用8279 可编程器件来完成, 使显示更为简洁1 当然, 哪些功能留给硬件完成, 哪些功能留给软件完成, 应根据具体系统综合考虑
2) 设计中若不可避免出现某一功能的执行时间过长而不能在系统时间片内执行完毕的情况下,可采用两种方法解决:
一是将模块任务分别安排在两相邻时间片内执行, 两模块通过内部产生消息联结; 二是和处理实时性要求很高的外部中断的方法一样改由专用CPU处理
3) 各任务模块在功能上应尽量相互独立, 以保证程序调试和维护的方便
4) 功能互斥的模块放在一个时间片1 这样既有效地利用时间片, 又起到互斥作用
由于系统是以分时原理设计的, 每个任务模块在给定的时间片完成预定的任务, 每个任务模块的执行是在有消息的前提下在相应的时间片内完成的1模块的执行时间很短, 代码的独立性强, 每个任务完成后即返回调度程序, 因此模块的重用性很好,并且避免了代码重入导致堆栈溢出的危险1由于系统采用模块结构, 因而系统结构清晰, 配置灵活, 调试与维护方便1 对程序的扩充更为方便,不用更改原有结构, 只需增加要扩充的模块即可
2 任务模块的调度
在单片机控制系统中分时多任务机制的实现是由调度程序完成的, 调度程序在每个时间片的开始取得控制1 这里借鉴W indow s 面向对象编程的原理, 在单片机编程中引入消息的概念, 将模块的执行条件转化为消息1 消息定义为: 当某个事件(如中断) 发生时, 事件处理程序(如中断服务程序) 设置相应的标志, 不同的标志即代表不同的消息1 模块之间状态变化、模块内部有状态请求而设置相应的标志等也可视作消息1 在本系统中定时中断产生的定时标志、采集到的某些外部信号(水位、温度到达设定值等)、甚至功能模块的某些结果均可作为消息,以驱动下一功能模块的执行1 因此, 本系统中多任务的调度实际上是根据消息来进行驱动的1 任务模块的实时模块在给定的时间片都要执行的, 因此一旦给定的时间片取得控制即执行相应的任务模块(此时定时中断产生消息) , 如数据采集、水位、温度监控等1 而给定的时间片内的功能模块在消息激活的前提下才会执行1 消息在多任务程序中的作用相当于桥梁, 使模块间既相互独立又相互连接1 在给定的时间片有消息时, 相应的功能模块会执行, 无消息时则任务模块会跳过1 任务模块的优先级在主循环中是均等的, 中断在后台运行, 中间用消息联结1消息在其消息响应模块中首先被复位, 以免同一时间片任务模块的重入。