2016-12-01 99 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