1. 硬件构件
独立编程的实体就是硬件构件,硬件构件分为内部构件和外部构件,内部构件比如系统初始化、定时器、Flash、串口等,外部构件比如LED开关、按钮、电机等。每个构件有独立模块。
2.设计基本原则
2.1 对每个硬件构件编写独立的驱动程序
每个构件对应一个头文件和源文件,如果构件是外部构件,则要在头文件用宏定义构件接在哪个脚上,头文件只声明供外部调用的功能函数,也就是说,其他人只要看头文件函数声明就知道如何使用此构件而无需去看源文件去阅读代码。
一般函数的命名规则是:构件_功能,比如初始化LED,函数名可以为LED_Init。如果一个函数只供构件功能函数内部调用,则此函数在源文件里面声明和实现,不出现在头文件里,并声明为static 函数,因为声明为static的函数只能供定义此函数的源文件使用,其他源文件看不到此函数。如果一个全局变量只供某模块使用,则可以把此全局变量定义为static,这样此变量只能在定义它的源文件中使用,其他源文件看不到此变量,所以不会产生命名冲突。
2.2 封装要完整、封装之间不能交叉
模块函数就实现此模块要实现的功能,模块内部之间不能相互调用,如果要调用则交给高端来处理,比如在Flash子程序里面不能调用串口,当然测试Flash子程序的时候例外,当测试完毕时,必须把调用串口子程序代码删除,此时Flash子程序可以通过返回值告诉高端,让高端根据返回值来决定是否调用串口子程序。
2.3 返回值问题
如果只返回一个基本类型的返回值,则用返回值返回此值也可,如果返回一个复杂类型的返回值,比如一个struct结构体,则用返回值返回的话要进行复制,开销很大,此时用传址方式返回,如果返回的值很多,可以把这些值定义在一个struct里面,通过指针形式返回。
2.4 函数编写
函数第一要命名合理,一看函数名就知道此函数的功能、操作的构件。函数的层次最好不要多于5级,一个是效率降低,再一个阅读性也变差,对每个函数注释清楚,所有的函数代码编写方式有一个统一的风格,注意对齐。函数中的堆栈变量使用前一定要负初值,在一个嵌入式的RAM一般比较少,注意不要堆栈溢出。尽量用效率高的方式编码,比如乘除可以用移位来实现。
如果编写的程序在16位控制器上运行,函数整型参数和局部整型变量要用16位,因为如果用8位的整型变量,系统要做多余的工作来防止8位溢出之类的事情,不仅不节省空间,还会降低效率,通过反汇编对比可以看出此现象。
3. 测试
测试是当模块编写完成后对其功能性的测试,先进行白盒测试,然后进行黑盒测试,测试要测试模块所有可能的输入,对非法的输入进行检测,一定测试全面。
4. 调用驱动程序
一般会在两个地方调用驱动程序,一个是main函数,一个是中断处理函数,可能有多个源文件包含相同的头文件。设计头文件的时候要避免重复定义问题,方法是:以定义LED模块为例,头文件如下编写:
#ifndef _LED_H
#define _LED_H
/*函数声明*/
#endif
5. 变量
变量分为全局变量、堆栈变量、函数内静态变量、文件内静态变量、寄存器变量。
寄存器变量是当某个变量频繁使用很多次的时候为了避免每次从内存中读它,而把它放在寄存器中来改变性能。
如果一个变量只在函数中使用,并且要一直存在,则命名为函数内静态变量,如果一个函数只在某个源文件中使用,此源文件各个函数通过此变量来通信,则此变量命名为文件内静态变量。
所有的变量要有一定的命名规范,全局变量前面加前缀g_,静态变量前面加前缀s_,寄存器变量前面加前缀r_,如果一个变量名由多个单词组成,单词之间可以用下划线分开,也可以是第一个单词字母大写,不管使用何种命名写法,全局要统一一致,不能两种混合使用。
6. 总体设计
每个系统编码之前一定要先设计,思路要弄清晰,之后才编码。大任务调用小任务,小任务如果全部正确,则大任务一定正确,知道某个小任务一定正确,但是大任务不正确调试的时候就可以把此小任务分割出去,不用去管,这样调试会更加有目的性,更加容易调试。
一个小灯可能就是一个很好的调试工具,所以不要忽略这个小灯,在系统初始化的时候通过闪亮小灯指示初始化成功很有必要性。
文章评论(0条评论)
登录后参与讨论