如何写出高效的单片机C语言程序代码
与之比较的。PC
对于单片机来说就截然不同了,一般的单片机的Flash
机的资源是少得可怜,为此我们必须想法设法榨尽其所有资源,将它的性能发挥到最佳,程序设计时必须
遵循以下几点进行优化:
1.
能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变
量就不要用长整型(long
量后不要超过变量的作用范围,如果超过变量的范围赋值,C
而且这样的错误很难发现。
2.
通常使用自加、自减指令和复合赋值表达式(如a-=1
程序代码,编译器通常都能够生成inc
的指令,有很多C
3.
可以使用运算量小但功能相同的表达式替换原来复杂的的表达式。
(1)
N=
说明:位操作只需一个指令周期即可完成,而大部分的C
完成,代码长、执行速度慢。通常,只要求是求2n
(2)
N=Pow(3,2)
说明:在有内置硬件乘法器的单片机中(如51
的求平方是通过调用子程序来实现的,乘法运算的子程序比平方运算的子程序代码短,执行速度快。
(3)
N=M*8
N=M/8
说明:通常如果需要乘以或除以2n,都可以用移位的方法代替。如果乘以2n,都可以生成左移
的代码,而乘以其它的整数或除以任何数,均调用乘除法子程序。用移位的方法得到代码比调用乘除法子
程序生成的代码效率高。实际上,只要是乘以或除以一个整数,均可以用移位的方法得到结果。如N=M*9
可以改为N=(M<<3)+M;
(4)
例如我们平时使用的延时函数都是通过采用自加的方式来实现。
void
{
UINT16
for(i=0;i
}
可以改为
void
{
UINT16
for(i=t;i>=0;i--)
for(j=1000;i>=0;j--)
}
说明:两个函数的延时效果相似,但几乎所有的C
个字节,因为几乎所有的MCU
4.
void
{
while(t--)
{
NOP();
}
}
可以改为
void
{
do
{
NOP();
}while(--t)
}
说明:使用do…while
5.
void
{
while(*str
{
UARTSendByte(*str++)
}
}
可以改为
void
{
register
while(*pstr
{
UARTSendByte(*pstr++)
}
}
说明:在声明局部变量的时候可以使用register
器中,而不是在堆栈中,合理使用这种方法可以提高执行速度。函数调用越是频繁,越是可能提高代码的
速度,注意register
6.
volatile
哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。一般来
说,volatile
a)
b)
c)
总之,volatile
更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码
就不再进行优化,从而可以提供对特殊地址的稳定访问。
7.
在数据校验实战当中,CRC16
校验值,效率更高,当校验数据量大的时候,使用查表法优势更加明显,不过唯一的缺点是占用大量的空
间。
//查表法:
code
0x0000,
0x8108,
0x1231,
0x9339,
0x2462,
0xa56a,
0x3653,
0xb75b,
0x48c4,
0xc9cc,
0x5af5,
0xdbfd,
0x6ca6,
0xedae,
0x7e97,
0xff9f,
0x9188,
0x1080,
0x83b9,
0x02b1,
0xb5ea,
0x34e2,
0xa7db,
0x26d3,
0xd94c,