我一直在使用mspgcc编译器处理MSP430G2553,作为介绍性程序,我开始使用闪烁的LED。我使用的代码如下:
#include <msp430.h>
unsigned int i;
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR |= 0x01; //Set P1.0 to output
for(;;)
{
P1OUT ^= 0x01;
i=0;
while(i<50000)
{
i++;
}
}
}
while循环执行提供延迟的工作。
我认为,由于上面的i
从0递增到某个值的while循环,为什么我不能使用递减循环。所以我尝试了以下代码。
#include <msp430.h>
unsigned int i;
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR |= 0x01; //Set P1.0 to output
for(;;)
{
P1OUT ^= 0x01;
i=50000
while(i>0)
{
i--;
}
}
}
这段代码没有工作,找不到原因,我开始知道全局变量i
需要提供&#34; volatile&#34;以防止编译器的优化,因为i
的值可以随时改变。
我的问题是在第一种情况下,i
的值也从0变为49999,那么为什么我们不使用&#34; volatile&#34;在那种情况下的修饰语?
上述每种情况的汇编代码如下:
案例1(递增循环)
main:
40B2 5A80 0120 MOV.W #0x5a80,&Watchdog_Timer_WDTCTL
P1DIR |= 0x01; //Set P1.0 to output
D3D2 0022 BIS.B #1,&Port_1_2_P1DIR
P1OUT ^= 0x01;
$C$L1:
E3D2 0021 XOR.B #1,&Port_1_2_P1OUT
i=0;
4382 0200 CLR.W &i
while(i<50000)
90B2 C350 0200 CMP.W #0xc350,&i
2FF8 JHS ($C$L1)
i++;
$C$L2:
5392 0200 INC.W &i
90B2 C350 0200 CMP.W #0xc350,&i
2FF2 JHS ($C$L1)
3FF9 JMP ($C$L2)
案例2(减少循环)
main:
40B2 5A80 0120 MOV.W #0x5a80,&Watchdog_Timer_WDTCTL
P1DIR |= 0x01; //Set P1.0 to output
D3D2 0022 BIS.B #1,&Port_1_2_P1DIR
P1OUT ^= 0x01;
$C$L1:
E3D2 0021 XOR.B #1,&Port_1_2_P1OUT
i=50000;
40B2 C350 0200 MOV.W #0xc350,&i
while(i>0)
9382 0200 TST.W &i
27F8 JEQ ($C$L1)
i--;
4382 0200 CLR.W &i
3FF5 JMP ($C$L1)
答案 0 :(得分:3)
简而言之,volatile
限定符告诉编译器一个对象具有超出其“视觉”的副作用。所以它不能优化对它的访问。
如果没有这个,编译器可以自由地优化掉整个循环,如果它可以证明这不会改变程序的可观察行为。请注意,这不能得到保证,在您的情况下,编译器似乎识别出一种代码模式,而不是另一种代码模式。但是你不能依赖于这个(而且那些编写代码的人缺乏基本的编码实践)。
在这两种情况下,volatile
都是必要的,但为了安全起见。请注意,编译器仍然可以优化代码;最好是另外将NOP
汇编器内在函数放入循环中。
注意:请参阅生成的汇编程序代码。优化后的代码很可能包含i = 0
而不是循环,或只是将i
保留为静态变量的默认值(也是0
)。