2016-12-01 105 views
1

我在AVR或STM32 MCU上等待一些真实世界事件的时间(例如,按下一个按钮3秒),并且遇到以下代码的问题:Loop“while”不满足中断条件

#define PRESS_BUTTON 
int waiting = 0; 
int t_ms = 0; // time counter 
//... 

int main(void) 
{   
    while(1) 
    {   
     waiting = t_ms + 3000; // waiting button 3 sec 

     while ((t_ms < waiting) && (!PRESS_BUTTON)) // infinite loop 
     {}     
     printf("out"); // not printed 
     waiting = t_ms = 0; 
    }  
} 

ISR(TIMER0_OVF_vect) // timer interrupt 
{ 
    t_ms++; 
} 

但是,如果我添加printf()while循环中,它的作品!

如果我使用do...while循环,也会发生同样的事情。这是什么造成的?

+3

'volatile'关键字的威力。更改为'volatile int t_ms = 0;' – LPs

+0

除了添加'volatile'外,您如何反弹按钮?这需要用软件或硬件完成,否则程序总是表现不佳。 – Lundin

+0

每5个满月只有一次我看到stackoverflow上正确需要的'volatile'。好问题。 –

回答

2

您需要使用挥发性

volatile int t_ms =0; 

挥发性告诉变量可能因改变外部因素编译申报t_ms,并且因为这个编译器不会认为它会保持不变。

换句话说,它会强制编译器检查每个循环,看看t_ms是否已经改变,而不是假设它永远不会改变。

+0

尽管假定原子性,但要小心,一般来说这对于任何非'sig_atomic_t'类型都是不安全的。特别是,这里讨论的8位AVR架构会分别读取低字节和高字节,因此在中断竞争的情况下可能会看到一个残缺的值。除掩蔽中断外,最简单的解决方法是依次读取MSB,LSB和MSB部分,如果第二次读取不匹配,则旋转(尽管超出单调递增计数器,但此策略可能会遇到ABA问题。) – doynax