通过对用例和系统结构分析,识别出来的类和关系。
出于可移植性的考虑,所有类被分成3个层次:
最顶层是功能逻辑类的抽象,MachineStting为机器设置类;Keys为按键类,Displayr为显示类,MotorController为电机控制器类。这些逻辑上的类与硬件无关,便于以后硬件修改,同时使得开发绕线机的不同版本变得非常容易,如从平绕机到开发环行机,从二轴绕线机到开发三轴绕线机。
中间层是外围硬件类的抽象,Flash为Flash存储类,用于存储设置的参数;Speaker为扬声器类;Panel为面板类;DCMoto/为直流电机类;StepMotor为步进电机类。
最底层是单片机及其内部功能模块类的抽象,H8/3062为单片机类,用于封装输入/输出口;Timer_KeyShake为按键防抖定时器;Timer_DCMotor为直流电机PWM脉冲产生定时器;Timer_DCCapture为直流电机圈数捕获定时器;Timer_StepMotor为步进电机PWM脉冲产生定时器。分这一层可以使得变换单片机类型非常容易,瑞萨H8/300H系列单片机在国内应用非常罕见,之所以选用这款是为了与国外产品的竞争,这样可以更快、更好地打开国际销路,但在选择这款单片机的同时已经做好了移植到ARM内核单片机的准备。
为了理解系统的动态行为,还应该用顺序图、协作图、状态图和活动图对系统动态行为进行描述。状态图对嵌入式系统的设计尤其重要,这里用其对MotorController的状态转换进行描述。
可以用时序图等对用例进行进一步的分析,“启动”按键按下后处理的时序图。
建模过程不是一个直线过程。它往往是一个演化、迭代的过程,不断地分析、评价、修改、再分析,才可能得到一个高质量的模型,为高质量的软件打下基础。
1.3 编码过程
Rose具有自动生成C++框架代码的功能。在Rose菜单中选择Tools→ANSI C++→Generate Code,可以生成C++的框架代码。
要用C编码,需要把C++代码稍作修改变成C代码。由于没有动态创建实体,所有的对象都是静态的。这使得修改工作极其简单——把“::”改成“_”即可。修改后的“_”前面的部分可以看成是对象名,后面的部分看成是成员函数名,源文件的修改。
头文件也需要做相应的修改,对变量的定义需要放到源文件里面。
代码修改完成后,剩下的就是C语言的编码过程了。编码时,当调用对象成员时,“.”操作符用“_”代替,则刚好对应上修改后的变量和函数。
2 进一步优化程序的方法
为了进一步提高程序的速度,还应对程序进行专门的优化,例如中断处理程序里面一两条指令引起的差异就非常明显。下面介绍几种优化办法。
①把成员函数定义成宏函数。由于面向对象数据隐藏的特点,对数据的操作需要以函数的形式提供,使得数据的操作效率变低。C++编程时,类的成员函数不能修改成宏,改为C函数后,就可以修改了;但这种优化最好在调试结束后进行,因为宏函数不方便错误定位。修改方法如图8所示。
②把成员函数定义成内联函数。
③程序中使用查表。对一些很消耗时间资源的非常复杂的运算,可以使用查表的方式。在步进电机的加减速控制中,加减速曲线一般采用指数曲线或者S曲线,运算量较大。可以事先把曲线对应的定时器上界寄存器的值离线计算出来,并片j数组保存起来,需要时直接读数组即可。这种方法通过牺牲空问来换取时间,但是牺牲的是相对宽余的ROM空间,还是比较划算的。
结语
绕线机项目获得了很好的效果,达到了系统的性能要求。测试时,发现的错误相比以前类似项目大大减少。更让人兴奋的是,测试中没有发现任何大的软件结构上的错误。这归功于Rose的前期可视化建模功能。编码之前可以很清楚地掌握系统的结构,这是面向对象设计相比传统方法的优势。
应用结果表明,这种开发方法是很实用的,可以优化程序结构、缩短开发周期,实现快速开发又不降低程序的效率;但这种方法的应用是有局限性的,对效率与空间要求不高的嵌入式系统,完全可以直接用C++编程,因此这种方法只适合于空间紧张、实时性要求比较高的系统。