中断多任务+状态机 单片机软件结构设计
习UML/C++,书中介绍tachniques for identifying dynamic behvior,方才豁然开朗。功夫在诗外,掌握C++,甚至C# JAVA,对理解嵌入式程序设计,会有莫大的帮助) 状态机的程序实现相当简单,第一种方法是用swich-case实现: } 另一种方法还是用更通用简洁的函数指针数组: const FUNCTIONPTR[] states = { state0, state1, …, stateM }; void RunTaskN() { (*states[state])(); } 下面是state machine控制的例子: void state0() { } void state1() { state++; } void state2() { state+=2; } void state3() { state--; } void state4() { delay = 100; state++; } void state5() { delay--; if (delay <= 0) state++; } void state6() { state=0; } 一个小技巧是把第一个状态state0设置为空状态,即: 这样,state =0可以让整个task停止运行,如果需要投入运行,简单的让state = 1即可。 以下是一个键盘扫描的例子,这里假设tick = 20 ms, ScanKeyboard()函数控制口线的输出扫描,并检测输入转换为键码,利用每个state之间20 ms的间隔去抖动。 EnumKey_NoKey = … struct StructKeyProcess key; void ProcessKey() { (*states[state])(); } 上面的键盘处理过程显然比通常使用标志去抖的程序简洁清晰,而且没有软件延时去抖的困扰。以此类推,各个任务都可以划分成一个个的state,每个state实际上占用不多的处理时间。某些任务可以划分成若干个子任务,每个子任务再划分成若干个状态。 (题外话:对于常数类型,建议使用enum分类组织,避免使用大量#define定义常数) 对于一些完全不能分割,必须独占的任务来说,比如我以前一个低成本应用中红外遥控器的软件解码任务,这时只能牺牲其他的任务了。两种做法:一种是关闭中断,完全的独占; 第二种,允许定时中断发生,保证某些时基register得以更新; 只要watchDogCounter不为0,那么中断正常返回到中断点,继续执行先前被中断的任务,否则,复位stack,重新进行任务循环。这种状况下,中断处理过程极短,对独占任务的影响也有限。 中断驱动多任务配合状态机的使用,我相信这是mcu下无os系统较好的设计结构。对于绝大多数mcu程序设计来说,可以极大的减轻程序结构的安排,无需过多的考虑各个任务之间的时间安排,而且可以让程序简洁易懂。缺点是,程序员必须花费一定的时间考虑如何切分任务。 下面是一段用C改写的CD Player中检测disc是否存在的伪代码,用以展示这种结构的设计技巧,原源代码为Z8 mcu汇编,基于Sony的DSP, Servo and RF处理芯片,通过送出命令字来控制主轴/滑板/聚焦/寻迹电机,并读取状态以及CD的sub Q码。这个处理任务只是一个大任务下用state machine切开的一个二级子任务,tick = 20 ms。 if (innerSwitch != ON) { SendCommand(EnumCommand_SlidingMotorBackward); timeout = MILLISECOND(10000); state++; } else
中断多任务状态机单片机软件结 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)