2017-01-09 40 views
-3

我最近在玩ATmega2560時遇到了一個問題,我真的不明白它有什麼問題。ATmega2560使用UART中斷來控制全局標誌

這是我的代碼。

主:

#include "Definitions.h" 

int main(void) { 
    Initialization(); 
    while (1) { 
     //_delay_ms(1); // or printf... 
     //wait for RXC flag 
     if (RxFlag) { 
      //wait for new byte in 
      //PORTB &= ~(1 << PB7); 
      PORTB |= (1 << PB7); 
      rxcount = 0; 
      UDR0 = 'R'; 
      RxFlag = false; 
      TxFlag = false; 
     } 
    } 
} 

IRQ:

#include "Definitions.h" 

ISR(USART0_RX_vect) { 
    while(!(UCSR0A & (1 << RXC0))) 
    //wait for RXC flag 
     ; 
    /* Loop-back test */ 
    //PORTB |= (1 << PB7); 
    //test_data = UDR0; 
    TxFlag = true; 
    //enableUDRI0(); 
    //PORTB &= ~(1 << PB7); 
    //PORTB |= (1 << PB7); 
    RxBuffer[rxcount++] = UDR0; 
    if(!(rxcount < RX_BUF_SZ)) { 
     //rxcount = 0; 
     PORTB |= (1 << PB7); 
     RxFlag = true; 
    } 
} 

ISR(USART0_UDRE_vect) { 
    while(!(UCSR0A & (1 << UDRE0))) 
    //wait for udr to be empty 
     ; 
    /* Loop-back test */ 
    UDR0 = 0x30 + rxcount; 
    disableUDRI0(); 
} 

的問題是,當我收到一些DATAS從USART,我試圖設置一個RxFlag能夠主動if語句在主循環。但是,直到我在if語句之前取消註釋該函數(可能是_delay_ms()或printf())之後,它才起作用。

這是沒有意義的。我記得的是,我不需要這些函數,它仍然可以設置全局變量來影響主循環。還是有我錯過的任何細節?請給我一些線索弄清楚,我很困惑。

+0

請在此處發佈您的代碼,而不是通過外部鏈接。 –

+3

一段時間進入ISR是一個糟糕的想法......曾經......我猜你是複製了一個非中斷驅動的代碼。 – LPs

+0

看起來有關於中斷如何工作的一些重大錯誤觀念。還有代碼缺失。閱讀[問]並按照建議! – Olaf

回答

0

這是不可能是明確的,但我認爲這解釋了你的問題,所以它可能是錯誤。

您不包括RXFlag的聲明,但我推測您並未聲明volatile。除非你這樣做,否則編譯器可以假定它知道關於該變量會發生什麼的一切。特別是它知道,除非main()調用任何其他函數,否則RxFlag的值永遠不會改變。所以它可以通過將它移到循環外面來優化if表達式。實際上它正在改變你的代碼是這樣的:

#include "Definitions.h" 

int main(void) 
{ 
    register bool x; 

    Initialization(); 

    x = RxFlag; 

    while (1) 
    { 
     //wait for RXC flag 
     if (x) //wait for new byte in 
     { 
      //PORTB &= ~(1 << PB7); 
      PORTB |= (1 << PB7); 
      rxcount = 0; 
      UDR0 = 'R'; 
      RxFlag = false; 
      TxFlag = false; 

     } 
    } 
} 

但是,如果main()調用另一個函數,編譯器將放棄試圖保持RxFlag超過這一呼籲的寄存器。另一個函數可能會改變RxFlag所在的寄存器。它必須將其推入堆棧或其他東西。再次讀取代碼和時間會更便宜,因此每次讀取循環時都會讀取它。

該錯誤的正確解決方法是聲明主線程和ISR之間共享的任何變量爲volatile

+0

使用gcc時,一半的AVR寄存器*被保存*。而gcc在優化時會利用這一點,甚至可以在函數調用中保留寄存器中的值。函數調用也可以內聯,因此對優化器來說,它甚至不會作爲調用發生。 – JimmyB