快捷搜索:

单片机C言语优化技巧

单片机C言语优化技巧

对程序进行优化,通常是指优化程序代码或程序执行速度。优化代码和优化速度实践 上是一个予盾的统一,一般是优化了代码的尺寸,就会带来执行时间的添加 ,假如 优化了程序的执行速度,通常会带来代码添加 的副作用,很难鱼与熊掌兼得,只能在设计时把握 一个平衡点。
一、程序结构的优化
1、程序的书写结构
虽然书写格局 其实不 会影响生成的代码质量,但是 在实践 编写程序时仍是 应该尊循一定的书写规则,一个书写明晰 、明了的程序,有利于今后 的维护。在书写程序时,特别是关于 While、for、do…while、if…elst、switch…case 等语句或这些语句嵌套组合时,应选用 “缩格”的书写形式,
2、标识符
程序中使用的用户标识符除要遵循标识符的命名规则以外,一般不要用代数符号(如a、b、x1、y1)作为变量名,应选取具有相关意义 的英文单词(或缩写)或汉语拼音作为标识符,以添加 程序的可读性,如:
count、number1、red、work 等。
3、程序结构
C 言语 是一种高级程序设计言语 ,提供了十分齐备 的规范化流程控制结构。因此在选用 C 言语 设计单片机应用体系 程序时,首要 要留意 尽可能选用 结构化的程序设计方法,这样能够使 整个应用体系 程序结构明晰 ,便于调试和维护。于一个较大的应用程序,通常将整个程序按功用 分红 若干个模块,不同模块完成不同的功用 。各个模块可以分别编写,乃至 还可以由不同的程序员编写,一般单个模块完成的功用 较为简略 ,设计和调试也相对容易一些。在C 言语 中,一个函数就能够 认为是一个模块。所谓程序模块化,不只 是要将整个程序划分红 若干个功用 模块,更重要的是,还应该留意 坚持 各个模块之间变量的相对独立性,即坚持 模块的独立性,尽量少使用全局变量等。关于 一些常用的功用 模块,还可以封装为一个应用程序库,以便需要时可以直接调用。但是 在使用模块化时,假如 将模块分红 太细太小,又会导致程序的执行功率 变低(进入和退出一个函数时保护和恢复存放 器占用了一些时间)。
4、定义 常数
在程序化设计过程中,关于 常常 使用的一些常数,假如 将它直接写到程序中去,一旦常数的数值发生变化,就有必要 逐个找出程序中所有的常数,并逐一进行修正 ,这样必定 会下降 程序的可维护性。因此,应尽量中选 用 预处理命令方式来定义 常数,并且 还可以避免输入过错 。
5、减少判断语句
可以 使用条件编译(ifdef)的当地 就使用条件编译而不使用if 语句,有利于减少编译生成的代码的长度。
6、表达式
关于 一个表达式中各种运算执行的优先顺序不太明确或容易稠浊 的当地 ,应中选 用 圆括号明确指定它们的优先顺序。一个表达式通常不能写得太凌乱,假如 表达式太凌乱,时间久了今后 ,自己也不容易看得懂,晦气 于今后 的维护。
7、函数
关于 程序中的函数,在使用之前,应对函数的类型进行说明,对函数类型的说明有必要 保证它与本来 定义 的函数类型一致,关于 没有参数和没有返回值类型的函数应加上“void”说明。假如 果需要缩短代码的长度,可以将程序中一些公共的程序段定义 为函数,在Keil 中的高级别优化就是这样的。假如 需要缩短程序的执行时间,在程序调试完毕 后,将部分函数用宏定义 来代替 。留意 ,应该在程序调试完毕 后再定义 宏,因为大大都 编译体系 在宏打开 之后才会报错,这样会添加 排错的难度。
8、尽量少用全局变量,多用部分 变量。因为全局变量是放在数据存储器中,定义 一个全局变量,MCU 就少一个能够使 用 的数据存储器空间,假如 定义 了太多的全局变量,会导致编译器无足够的内存可以分配。而部分 变量大多定位于MCU 内部的存放 器中,在绝大大都 MCU 中,使用存放 器操作速度比数据存储器快,指令也更多更活络 ,有利于生成质量更高的代码,并且 部分 变量所的占用的存放 器和数据存储器在不同的模块中可以重复使用 。
9、设定适合 的编译程序选项
许多编译程序有几种不同的优化选项,在使用前应了解 各优化选项的意义 ,然后选用最适合 的一种优化方式。通常状况 下一旦选用第一流 优化,编译程序会近乎病态地寻求 代码优化,可能会影响程序的正确性,导致程序运转 犯错 。因此应熟悉所使用的编译器,应知道哪些参数在优化时会遭到 影响,哪些参数不会遭到 影响。
在ICCAVR 中,有“Default”和“Enable Code Compression”两个优化选项。
在CodeVisionAVR 中,“Tiny”和“small”两种内存模式。
在IAR ==有7 种不同的内存模式选项。
在GCCAVR 中优化选项更多,一不当心 更容易选到不恰当的选项。
二、代码的优化
1、选择适合 的算法和数据结构
应该熟悉算法言语 ,知道各种算法的优缺点,详细 资料请拜见 相应的参考资料,有很多核算 机书本 上都有介绍。将比较慢的顺序查找法用较快的二分查找或乱序查找法代替 ,刺进 排序或冒泡排序法用快速排序、合并排序或根排序代替 ,都可以大大提高程序执行的功率 。.选择一种适合 的数据结构也很重要,比如你在一堆随机存放的数中使用了很多 的刺进 和删除指令,那使用链表要快得多。
数组与指针具有十分密码的关系,一般来说,指针比较活络 简洁,而数组则比较直观,容易了解 。关于 大部分的编译器,使用指针比使用数组生成的代码更短,执行功率 更高。但是 在Keil 中则相反,使用数组比使用的指针生成的代码更短。
2、使用尽量小的数据类型
可以 使用字符型(char)定义 的变量,就不要使用整型(int)变量来定义 ;可以 使用整型变量定义 的变量就不要用长整型(long int),能不使用浮点型(float)变量就不要使用浮点型变量。当然,在定义 变量后不要超过变量的作用规模 ,假如 超过变量的规模 赋值,C 编译器其实不 报错,但程序运转 成绩却错了,并且 这样的过错 很难发现。在ICCAVR 中,可以在Options 中设定使用printf 参数,尽量使用底子 型参数(%c、%d、%x、%X、%u 和%s 格局 说明符),少用长整型参数(%ld、%lu、%lx 和%lX 格局 说明符),至于浮点型的参数(%f)则尽量不要使用,其它C 编译器也一样。在其它条件不变的状况 下,使用%f 参数,会使生成的代码的数量添加 很多,执行速度下降 。
3、使用自加、自减指令
通常使用自加、自减指令和复合赋值表达式(如a-=1 及a+=1 等)都可以 生成高质量的程序代码,编译器通常都可以 生成inc 和dec 之类的指令,而使用a=a+1 或a=a-1 之类的指令,有很多C 编译器都会生成二到三个字节的指令。在AVR 单片适用的ICCAVR、GCCAVR、IAR 等C 编译器以上几种书写方式生成的代码是一样的,也能够 生成高质量的inc 和dec 之类的的代码。
4、减少运算的强度
能够使 用运算量小但功用 相同的表达式替换本来 凌乱的的表达式。如下:
(1)、求余运算。
a=a%8;
可以改为:
a=a&7;
说明:位操作只需一个指令周期即可完成,而大部分的C 编译器的“%”运算均是调用子程序来完成,代码长、执行速度慢。通常,只需 求是求2n 方的余数,均能够使 用位操作的方法来代替 。
(2)、平方运算
a=pow(a,2.0);
可以改为:
a=a*a;
说明:在有内置硬件乘法器的单片机中(如51 系列),乘法运算比求平方运算快得多,因为浮点数的求平方是通过调用子程序来完成 的,在自带硬件乘法器的AVR 单片机中,如ATMega163 中,乘法运算只需2 个时钟周期就能够 完成。既使是在没有内置硬件乘法器的AVR 单片机中,乘法运算的子程序比平方运算的子程序代码短,执行速度快。
假如 是求3 次方,如:
a=pow(a,3.0);
更改为:
a=a*a*a;
则功率 的改善更显着 。
(3)、用移位完成 乘除法运算
a=a*4;
b=b/4;
可以改为:
a=a2;
说明:通常假如 需要乘以或除以2n,都可以用移位的方法代替 。在ICCAVR 中,假如 乘以2n,都可以生成左移的代码,而乘以其它的整数或除以任何数,均调用乘除法子程序。用移位的方法得到代码比调用乘除法子程序生成的代码功率 高。实践 上,只需 是乘以或除以一个整数,均可以用移位的方法得到成绩,如:
a=a*9
可以改为:
a=(a

您可能还会对下面的文章感兴趣: