首页 理论教育51单片机案例设计及优化

51单片机案例设计及优化

【摘要】:如上述C代码中,把延时函数的定义删除了,然后把延时函数的实现搬到main函数的上面,编译后程序代码减少到63个字节,减少了4个字节,如图6-5所示。图6-4 编译结果2图6-5 编译结果3省略函数形参函数带形参,是为了在函数调用时传递实参,不但可以避免重复代码出现,还可以通过传递不同的实参值多次调用函数且实现不同的函数功能,总体代码也会得到精简。

在Keil软件中输入如下C代码:

978-7-111-49736-3-Chapter06-2.jpg

这是控制P2.0发光二极管闪烁的C源码,这个源码在KeiluVision4生成的程序代码是67个字节,如图6-1所示,图中code=67说明上述C代码编译后为67个字节。而这67个字节是编译后按照汇编语言的字节数进行计算的,如图6-2所示。下面就采用几种方法来提高这个程序的效率

978-7-111-49736-3-Chapter06-3.jpg

图6-1 编译结果1

978-7-111-49736-3-Chapter06-4.jpg

图6-2 反汇编结果

(1)尽量定义局部变量

单片机程序的全局变量一般是放在通用数据存储器(RAM)中,而局部变量一般是放在特殊功能寄存器中。上述C程序的执行状态如图6-3所示。图中的箭头指向下一条将要执行的指令。在Delayms(500)中i、j都为局部变量,因此放在寄存器中;Delayms(500)执行后j=120,由图6-3左边部分可知r3=Ox78=120,因此i保存在r3中;r4r5=OxOlf4=500,因此i保存在r4r5中。

978-7-111-49736-3-Chapter06-5.jpg

图6-3 程序执行状态

处理寄存器数据的速度比处理RAM数据要快,如果在一个局部函数里调用一个全局变量将会多生成代码。所以,少定义全局变量,多定义局部变量。如上述C代码中,如果把延时函数里的i和j定义为全局变量,编译后程序代码会增加到79个字节,多了12个字节,如图6-4所示。

(2)省略函数定义

在一个单片机程序里我们习惯在main函数的前面先定义被调用函数,然后在main函数的下面再实现被调用函数。这样的写法固然是一个好习惯,但每定义一个函数会增加代码,而且函数形参数据类型越大,形参越多,增加的代码就越多。如果不定义,编译器又报错。由于C编译器的编译顺序是从上往下编译,只要被调用的函数在主调函数调用之前实现就没有问题了。所以,优化的写法是不用定义函数,但要按先后顺序(被调用函数一定要在主调函数之前写好)来写函数实现,最后再写main函数。这样做编译器不但不会报错,而且代码得到精简。如上述C代码中,把延时函数的定义删除了,然后把延时函数的实现搬到main函数的上面,编译后程序代码减少到63个字节,减少了4个字节,如图6-5所示。

978-7-111-49736-3-Chapter06-6.jpg

图6-4 编译结果2

978-7-111-49736-3-Chapter06-7.jpg

图6-5 编译结果3

(3)省略函数形参

函数带形参,是为了在函数调用时传递实参,不但可以避免重复代码出现,还可以通过传递不同的实参值多次调用函数且实现不同的函数功能,总体代码也会得到精简。在实际编程时,我们只要稍加注意,还可以进一步精简代码。对于不是多次调用或者多次调用但实参值不变的函数,可以省略函数形参。如上述C代码中的延时函数,把它改写成不带形参的函数:

978-7-111-49736-3-Chapter06-8.jpg

编译后,程序代码变成56个字节,精简了11个字节,如图6-6所示。

(4)改换运算符(www.chuimin.cn)

在第(2)步的基础上进行修改。

C运算符的运用也会影响程序代码的数量。如上述C代码中,把延时函数里的自加运算符改成自减运算符后,即

978-7-111-49736-3-Chapter06-9.jpg

编译后,程序代码变成65个字节,精简了2个字节,如图6-7所示。

978-7-111-49736-3-Chapter06-10.jpg

图6-6 编译结果4

978-7-111-49736-3-Chapter06-11.jpg

图6-7 编译结果5

(5)选择合适的数据类型

在第(2)步的基础上进行修改。

C语言里选择变量的数据类型很讲究,变量的数据类型过小满足不了程序的要求,过大则会占用太多的RAM资源。数据类型定义也影响程序代码的大小,而且这个影响还比较大。如上述C代码中,延时函数里的局部变量j定义的数据类型明显偏大,如果把它由unsigned int改成unsigned char,编译后,程序代码变成55个字节,精简了12个字节,如图6-8所示。

(6)直接嵌入代码

在程序里如果某个函数只调用一次,而又要求代码提高执行速度,建议不要采用调用函数的形式,而应该将该函数里的代码直接嵌入主调函数里,代码执行效率会大大提高。

(7)使用效率高的C语句

C语言里有一个三目运算符“?”,俗称“问号表达式”。很多程序员都很喜欢使用,因为它逻辑清晰、表达简洁。例如,c=(a>b)?a+1:b+1;实际上等效于以下的if...else结构:

978-7-111-49736-3-Chapter06-12.jpg

图6-8 编译结果6

978-7-111-49736-3-Chapter06-13.jpg

可以看到,使用问号表达式,语句相当简洁,但执行效率很低,远没有if...else语句效率高。所以,当程序要求提高执行速度时,建议不要使用问号表达式。

另外,do-while语句也比while语句的效率高。

代码的效率问题,不是编程中的主要问题,除了程序要求较高的执行速度或者单片机的ROM和RAM不够用时才会考虑。一般情况下,还要兼顾其他问题。如果仅追求高效率的代码,可能会影响代码的可读性和可维护性。