浅谈8051单片机编程中C语言代码优化
曾红兵
(湖南冶金职业技术学院,湖南株洲412011)
摘 要:根据8051单片机和C51编译器的特点,介绍了几种提高C51编译器生成8051单片机代码效率的方法。
关键词:8051单片机;C语言;代码优化
中图分类号:TP335 文献标识码:A 文章编号:1672-7412(2007)03-027-03
1 引言
8051单片机是目前国内外工业测量控制领域内作用极为广泛的一类8位微控制器,它的特点是使用方便灵活,外围硬件支持十分丰富,世界上许多大的半导体生产厂商,如At mel、Dallas、Philip s、SST、TI等公司都推出了具有各自特点的增强型8051系列单片机。汇编语言曾是单片机软件开发工程师进行软件开发的唯一选择,但汇编语言程序的可读性和可移植性较差,采用汇编语言编写单片机应用程序的时间周期较长,且调试和排错比较困难。为了提高单片机应用系统的开发效率,世界上许多软件公司都致力于8051单片机高级语言编译器的开发研究,使用户从烦琐的汇编语言中解脱出来。
C语言是一种特别适合于开发计算机操作系统的高级语言,它兼顾了多种高级语言的特点,并具备汇编语言的功能,支持当前程序设计中广泛采用的由顶向下的结构化程序设计技术,又具有直接对计算机硬件进行操作(如对内存地址的操作,移位操作等)的特点。目前,C语言已逐步成为国内外开发单片机的主流语言。
单片机由于受功耗、成本和体积等因素的制约,其处理能力和存储空间与桌面系统处理器相比,存在较大差距,故对程序运行的空间和时间要求较苛刻。因此,代码优化是在单片机高级语言编程时不容忽视的一个问题。
2 C语言代码优化的实现2.1 变量定位
对于代码大小和执行速度影响最大的是存储器的模式。使用SMALL模式对源程序进行编译可以产生长度最小和速度最快的代码。在SMALL模式下,所有的变量(除非在声明时指定了存储器的类型)都将定位在8051单片机的片内RAM中,而访问片内的RAM速度最快(一般只有1~2个机器周期),同时产生的代码比COM2 PACT或L AR GE模式小得多。
当程序中用到的变量较多时,由于受到片内RAM的限制,所有的变量不可能全部放到片内RAM中,必须将某些变量放入其它的存储器空间,此时,如果让编译器自动完成变量定位的方法虽然简单,但可能导致代码的长度增加,执行效率降低。解决这一问题的方法是由用户将常用到的一些数据对象存放在片内
RAM中,而将访问较少的变量定义成xdata类型存放在外部RAM 中。通常字符串缓冲区和大型数组可以被定义为xdata类型而不会对代码长度和执行效率造成太大的影响[1]。
汇编语言转c语言的软件2.2 合理地选择数据和变量的类型
8051系统单片机为8位的CPU,它对于单字节数据的操作比多字节数据要方便得多,能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变量就不要用长整型(long int)。例如:两个char类型的数据相乘,恰好与8051指令“MUL AB”相
第7卷第3期湖南冶金职业技术学院学报Vol.7 No.3 2007年9月Journal of Hunan Metallurgical Professional Technology College Sep. 2007
3收稿日期:2007-03-09
作者简介:曾红兵(1979-),男,湖南嘉禾人,湖南冶金职业技术学院教师,工学硕士,研究方向:检测技术与自动化。
符,而如果采用int类型数据相乘则需调用C51编译器的函数。当然,在定义变量后不要超过变量的作用范围,如果超过变量的范围赋值,C编译器并不报错,但程序运行结果却错了,而且这样的错误很难发现。
8051单片机不支持带符号数的运算,对于带符号数的操作,C51编译器将产生更多的代码,因此建议尽可能的使用unsigned类型的数据将使生成的代码小得多。
函数中使用内存数目不大的变量尽量定义为局部变量,尽可能的利用局部变量,局部变量访问速度比较快,且不单独占用内存,因此可提高内存的重复利用率。
2.3 选择合适的算法和数据结构
应该熟悉算法语言,知道各种算法的优缺点,将比较慢的顺序查法用较快的二分查代替,插入排序或冒泡排序法用快速排序、合并排序或根排序代替,都可以大大提高程序执行的效率。选择一种合适的数据结构也很重要,比如你在一堆随机存放的数中使用了大量的插入和删除指令,那使用链表要快得多。
数组与指针语句具有十分密切的关系,一般来说,指针比较灵活简洁,而数组则比较直观,容易理解。对于大部分的编译器,使用指针比使用数组生成的代码更短,执行效率更高。但是在Keil中则相反,使用数组比使用指针生成的代码更短。
2.4 减少运算的强度
可以使用运算量小但功能相同的表达式替换原来复杂的表达式。如下:(1)求余运算。
a=a%8;可以改为:a=a&7;
说明:位操作只需一个指令周期即可完成,而大部分的C编译器的“%”运算均是调用子程序来完成,代码长、执行速度慢。通常,只要是求2n 方的余数,均可使用位操作的方法来代替。
(2)平方运算
a=pow(a,2);可以改为:a=a3a;
8051系列单片机内置硬件乘法器,乘法运算比求平方运算快得多。
如果是求3次方,如:a=pow(a,3);更改为: a=a3a3a;
则效率的改善更明显。
(3)用移位实现乘除法运算
a=a34;b=b/4;可以改为:a=a<<2;b=b>>2;
通常如果需要乘以或除以2n,都可以用移位的方法代替。而乘以其它的整数或除以任何数,均调用乘除法子程序。用移位的方法得到代码比调用乘除法子程序生成的代码效率高。实际上,只要是乘以或除以
一个整数,均可以用移位的方法得到结果,如:a=a
35可以改为:a=(a<<2)+a
(4)用自加、自减指令
通常使用自加、自减指令和复合赋值表达式(如a-=1及a+=1等)都能够生成高质量的程序代码,编译器通常都能够生成inc和dec之类的指令,而使用a=a+1或a=a-1之类的指令,有很多C编译器都会生成二到三个字节的指令。
2.5 循环程序设计
一般而言,程序的内循环(特别是最内循环)是重点要改进的地方,因为它们往往是程序中经常执行的部分。让这些部分尽可能地提高效率,有可能使我们以最小的代价获得最大的利益。对于一些不需要循环变量参加运算的任务可以把它们放到循环外面,这里的任务包括表达式、函数的调用、指针运算、数组访问等,应该将没有必要执行多次的操作全部集合在一起,放到初始化程序中进行。
其次,尽量以0作为分支的条件,例如,通常的延时函数均采用自加的形式:
void delay(void)
{
unsigned int i;
for(i=0;i<1000;i++)
;
}
将其改为自减延时函数:
void delay(void)
{
unsigned int i;
for(i=1000;i>0;i--)
;
}
两个函数的延时效果相似,但几乎所有的C 编译对后一种函数生成的代码均比前一种代码少1~3个字节,因为几乎所有的单片机均有为0转移的指令,采用后一种方式能够生成这类指令。在使用while循环时也一样,使用自减指令控制
82湖南冶金职业技术学院学报 第3期
循环会比使用自加指令控制循环生成的代码减少1~3个字母。但是在循环中有通过循环变量“i ”
读写数组的指令时,使用预减循环时有可能使数组超界,要引起注意。2.6 查表
在程序中一般不进行非常复杂的运算,如浮点数的乘除及开方等,以及一些复杂的数学模型的插补运算,对这些即消耗时间又消费资源的运算,应尽量使用查表的方式,并且将数据表置于程序存储区,减少了程序执行过程中计算的工作量。
另外,使用在线汇编及将字符串和一些常量
保存在程序存储器中,均有利于代码优化。3 总结
和早期的编译器相比,当前的C51在功能和编译效率方面都有了解很大的提高,随着单片机硬件资源的不断丰富,程序员将有更多的精力投入到产品功能的设计上。参考文献
[1]徐爱钧,彭秀华编著.Keil CX51V7.0单片机高级语言编程与uVision2应用实践[M ].北京:电子工业出版社,2004.
On C Language Code Optimization in Progoramming of 8051SCM
ZEN G Hong -bing
(Hunan Metallurgical Professional Technology College ,Zhuzhou ,Hunan ,412000China )
Abstract :According to t he characteristic of t he 8051SCM and t he C51compiler ,several met hods are int roduced to enhance t he efficiency t hat t he C51cornplier p rocluces 8051SCM code.Key words :8051SCM ;C language ;code optimization
[责任编辑:尹志诚]
9
2第3期 曾红兵:浅谈8051单片机编程中C 语言代码优化
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论