导航:首页 > 操作系统 > 单片机代码优化

单片机代码优化

发布时间:2024-03-24 10:28:38

1. 如何写出高效的单片机C语言程序代码

由于单片机的性能同电脑的性能是天渊之别的,无论从空间资源上、内存资源、工作频率,都是无法
与之比较的。PC 机编程基本上不用考虑空间的占用、内存的占用的问题,最终目的就是实现功能就可以了。
对于单片机来说就截然不同了,一般的单片机的Flash 和Ram 的资源是以KB 来衡量的,可想而知,单片
机的资源是少得可怜,为此我们必须想法设法榨尽其所有资源,将它的性能发挥到最佳,程序设计时必须
遵循以下几点进行优化:

1. 使用尽量小的数据类型
能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变
量就不要用长整型(long int),能不使用浮点型(float)变量就不要使用浮点型变量。当然,在定义变
量后不要超过变量的作用范围,如果超过变量的范围赋值,C 编译器并不报错,但程序运行结果却错了,
而且这样的错误很难发现。

2. 使用自加、自减指令
通常使用自加、自减指令和复合赋值表达式(如a-=1 及a+=1 等)都能够生成高质量的
程序代码,编译器通常都能够生成inc 和dec 之类的指令,而使用a=a+1 或a=a-1 之类
的指令,有很多C 编译器都会生成二到三个字节的指令。

3. 减少运算的强度
可以使用运算量小但功能相同的表达式替换原来复杂的的表达式。
(1) 求余运算
N= N %8 可以改为N = N &7
说明:位操作只需一个指令周期即可完成,而大部分的C 编译器的“%”运算均是调用子程序来
完成,代码长、执行速度慢。通常,只要求是求2n 方的余数,均可使用位操作的方法来代替。
(2) 平方运算
N=Pow(3,2) 可以改为N=3*3
说明:在有内置硬件乘法器的单片机中(如51 系列),乘法运算比求平方运算快得多, 因为浮点数
的求平方是通过调用子程序来实现的,乘法运算的子程序比平方运算的子程序代码短,执行速度快。
(3) 用位移代替乘法除法
N=M*8 可以改为N=M<<3
N=M/8 可以改为N=M>>3
说明:通常如果需要乘以或除以2n,都可以用移位的方法代替。如果乘以2n,都可以生成左移
的代码,而乘以其它的整数或除以任何数,均调用乘除法子程序。用移位的方法得到代码比调用乘除法子
程序生成的代码效率高。实际上,只要是乘以或除以一个整数,均可以用移位的方法得到结果。如N=M*9
可以改为N=(M<<3)+M;
(4) 自加自减的区别
例如我们平时使用的延时函数都是通过采用自加的方式来实现。
void DelayNms(UINT16 t)
{
UINT16 i,j;
for(i=0;i<t;i++)
for(j=0;i<1000;j++)
}
可以改为
void DelayNms(UINT16 t)
{
UINT16 i,j;
for(i=t;i>=0;i--)
for(j=1000;i>=0;j--)
}
说明:两个函数的延时效果相似,但几乎所有的C 编译对后一种函数生成的代码均比前一种代码少1~3
个字节,因为几乎所有的MCU 均有为0 转移的指令,采用后一种方式能够生成这类指令。

4. while 与do...while 的区别
void DelayNus(UINT16 t)
{
while(t--)
{
NOP();
}
}
可以改为
void DelayNus(UINT16 t)
{
do
{
NOP();
}while(--t)
}
说明:使用do…while 循环编译后生成的代码的长度短于while 循环。

5. register 关键字
void UARTPrintfString(INT8 *str)
{
while(*str && str)
{
UARTSendByte(*str++)
}
}
可以改为
void UARTPrintfString(INT8 *str)
{
register INT8 *pstr=str;
while(*pstr && pstr)
{
UARTSendByte(*pstr++)
}
}
说明:在声明局部变量的时候可以使用register 关键字。这就使得编译器把变量放入一个多用途的寄存
器中,而不是在堆栈中,合理使用这种方法可以提高执行速度。函数调用越是频繁,越是可能提高代码的
速度,注意register 关键字只是建议编译器而已。

6. volatile 关键字
volatile 总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在
哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。一般来
说,volatile 关键字只用在以下三种情况:
a) 中断服务函数中修改的供其它程序检测的变量需要加volatile(参考本书高级实验程序)
b) 多任务环境下各任务间共享的标志应该加volatile
c) 存储器映射的硬件寄存器通常也要加volatile 说明,因为每次对它的读写都可能由不同意义
总之,volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素
更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码
就不再进行优化,从而可以提供对特殊地址的稳定访问。

2. stm8s003单片机写OLED的代码内存不够怎么办

stm8s008空间大小是8K 使用的时候会出现空间不够用的情况,这个时候要对软件进行一些设置,从而优化程序大小。

1,修改优化等级,如下图所示,这样会优化掉无关的函数,将代码优化到最大程度

2,如果代码有多个数组,而ram实际空间不够使用的时候,修改下面的参数,最大修改为0xfff。

3,当二维数组定义完报错,无法容纳的时候,在数组前面加上NEAR可解决报错

例如:

NEAR u8 buff[10][10] = {********};

4,当代码还是很多的时候就要从代码逻辑和代码本身一点点的扣 能用数组代替的尽量不用代码,能用u8的不用u16

3. 51单片机ram不够用,怎么优化程序

1.肯定的,嵌套越多,要压栈保存的信息就越多,占用的RAM就越多了,对51来说,最多就是CPU内256字节的RAM。

2.是的。

3.没用过这芯片……我用的最多的是AVR

4因为你定义了一个pagebuf[512],512字节啊!51单片机的data撑死才256字节(还没算压栈保存数据需要的RAM),所以编译器自动将这个数组放在了XDATA中。

4. 如何优化单片机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=a 2; b=b 2;说明:通常如果需要乘以或除以2n,都可以用移位的方法代替。在 ICCAVR 中,如果乘以2n,都可以生成左移的代码,而乘以其它的整数或除以任何数,均调用乘除法子程序。用移位的方法得到代码比调用乘除法子程序生成的代码效率高。实际上,只要是乘以或除以一个整数,均可以用移位的方法得到结果,如:a=a*9 可以改为:a=(a 3)+a 5、循环(1)、循环语对于一些不需要循环变量参加运算的任务可以把它们放到循环外面,这里的任务包括表达式、函数的调用、指针运算、数组访问等,应该将没有必要执行多次的操作全部集合在一起,放到一个init 的初始化程序中进行。(2)、延时函数:通常使用的延时函数均采用自加的形式: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 个字节,因为几乎所有的MCU 均有为0 转移的指令,采用后一种方式能够生成这类指令。在使用while 循环时也一样,使用自减指令控制循环会比使用自加指令控制循环生成的代码更少 1~3 个字母。但是在循环中有通过循环变量"i"读写数组的指令时,使用预减循环时有可能使数组超界,要引起注意。(3)while 循环和do…while 循环用 while 循环时有以下两种循环形式:unsigned int i;i=0;while(i 1000){i++;//用户程序}或:unsigned int i;i=1000;do i--;//用户程序 while(i 0);在这两种循环中,使用do…while 循环编译后生成的代码的长度短于while 循环。6、查表在程序中一般不进行非常复杂的运算,如浮点数的乘除及开方等,以及一些复杂的数学模型的插补运算,对这些即消耗时间又消费资源的运算,应尽量使用查表的方式,并且将数据表置于程序存储区。如果直接生成所需的表比较困难,也尽量在启动时先计算,然后在数据存储器中生成所需的表,后以在程序运行直接查表就可以了,减少了程序执行过程中重复计算的工作量。7、其它比如使用在线汇编及将字符串和一些常量保存在程序存储器中,均有利于优化。

5. 单片机 程序如何优化

如果用的是C语言的话,有几点可以进行参考:
1 尽量减少全局变量,除非确实有必要,否则数据可以通过函数进行传递
2 赋值的时候用移位符代替'=',这样表面看来没有什么区别,但是当编译之后你就会发现移位符比'='执行效率要高
3 给程序加注释,提高可读性

6. C 单片机 开不开优化

开优化。C单片机如不开优化直接使用,程序的执行速度会很慢,而开了优化后优化了代码,可以大幅增加程序运行的效率,以节省宝贵的时间,所以很有必要开优化。

阅读全文

与单片机代码优化相关的资料

热点内容
编程猫拔萝卜文字评价模板 浏览:246
cmdjava命令 浏览:237
扫描版pdf转文字版 浏览:532
单片机专用寄存器 浏览:495
学习python的手册 浏览:676
vue编译成js文件 浏览:90
给单片机供电的电池 浏览:341
什么app是分享教育的 浏览:899
可视化编程java 浏览:83
人工智能温控器算法 浏览:376
大号文件夹多少钱一个 浏览:572
pdf阅读器打开文件 浏览:98
winrar解压日文文件 浏览:38
什么app可以看广东珠江电视台 浏览:75
linux移动文件位置 浏览:144
循环码与卷积码编译原理 浏览:808
进化算法和启发式算法的区别 浏览:602
android组件是什么 浏览:973
安卓手机微信怎么同步信息 浏览:183
小人pdf 浏览:806