IAR FOR AVR 编译环境中优化要注意的问题
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
在用IAR开发C程序时,开发环境提供了一个优化的选项,有4档,即None/Low/Medium/High。但在实际应用时要注意,不是什么情况下都可以进行优化,有时在没有优化时运行的代码,优化后则不能正常运行了。(这个现象在用WINAVR软件开发时更严重,本人就是因为觉得WINAVR这个问题比较严重才转到IAR环境的)
例如,下面的程序是让LED闪烁:
#include <ioavr.h>
// 定义一个宏操作
#define _BV(x) (1<<x)
// 定义LED对应的端口
#define LED 0
int main(void)
{
unsigned int k;
PORTB = _BV(LED); // 端口B的第0位置1
DDRB = _BV(LED); // 设置端口B的第0位为输出
while(1) // 进入无限循环
{
PORTB = PORTB & ~_BV(LED); // PB0<-0,点亮LED
for(k=0;k<60000;k++);
PORTB = PORTB | _BV(LED); // PB0<-1,熄灭LED
for(k=0;k<60000;k++);
}
}
在没有优化时,或者优化级别为Low或Medium时,可以看出LED是在闪烁,或者用示波器可以测出,PB0输出的是一个频率较低的方波。
但如果我们选了优化级别为High,这时就看不出来LED在闪烁了,或者用示波器可以测出,PB0输出的是一个频率较高的方波。
从C语言是看不出任何问题的,只能从编译后的汇编语言找问题。首先看一下在优化级别为Medium时,main函数对应的机器码,如下图所示:
从汇编代码中,我们可以看出,当对PB0端口操作后,程序进行了延时,(R25,R24)寄存器对作为变量k,进行了加1运算,和判断大小。
但如果我们选择了优化级别为High时,main函数的代码就变成如下图所示:
很明显看出,当对PB0端口设置为0后,紧接的下一条指令就是设置1的指令,然后又跳转回来,中间的延时完全被优化掉了,当然运行结果就是在PB0端口上看到一个频率较高的方波了。
如果我们确实需要对代码优化,可又需要这样的软件延时,那应该怎么办呢?答案是只要将上面的变量k定义成volatile类型即可,修改后的程序如下:
#include <ioavr.h>
// 定义一个宏操作
#define _BV(x) (1<<x)
// 定义LED对应的端口
#define LED 0
int main(void)
{
volatile unsigned int k;
PORTB = _BV(LED); // 端口B的第0位置1
DDRB = _BV(LED); // 设置端口B的第0位为输出
while(1) // 进入无限循环
{
PORTB = PORTB & ~_BV(LED); // PB0<-0,点亮LED
for(k=0;k<60000;k++);
PORTB = PORTB | _BV(LED); // PB0<-1,熄灭LED
for(k=0;k<60000;k++);
}
}
从汇编代码中,我们可以清楚地看见,当进行了PB0端口操作后,程序调用Subroutine0和Subroutine1分别完成加1运算和大小判别,从而实现了软件延时。
总之,当遇到优化后与优化前代码实现的功能不一样时,不妨从汇编代码进行分析一下。这样有利于解决问题。
<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2010-5-24
文章评论(0条评论)
登录后参与讨论