2015-02-09 89 views
0

我開始使用Arduino Due來完成某些需要UART的項目工作,並且看起來像UART中斷和I/O之間的交互看起來很混亂。UART中斷禁用Sam3X8E/Arduino上的I/O由於

我的第一段代碼是建立UART的小程序,通過在收到TXBE中斷後加載發送緩衝區來連續發送數據。我將UART輸出連接到示波器,並將另一個I/O引腳設置爲通用輸出,該輸出將翻轉狀態,因此當發送緩衝器重新加載時用於觸發示波器。問題是我看到UART數據並且看起來不錯,但I/O沒有翻轉。在這一點上,我的loop()例程是空的,所以我建立了另一個輸出端口,並在loop()剛剛切換其狀態作爲理智檢查。除UART之外,仍然沒有輸出。

下面是我最終的代碼:(!沒有足夠的聲譽這裏發表圖片)

uint32_t tempo; // 32-bit temporary variable 
boolean flag = true; 

void UART_Handler(void) { 
    REG_UART_THR = 0x6DL; // load data into the transmit buffer 
    if (flag) { 
    REG_PIOD_SODR = 0x02L; // drive PD1 high 
    flag = false; 
    } else { 
    REG_PIOD_CODR = 0x02L; // drive PD1 low 
    flag = true; 
    } 
} 

void setup() { 
    // set up the UART I/O 
    REG_PIOA_IDR = 0x0300L; // disable interrupts on PA8 and PA9 
    tempo = REG_PIOA_ABSR; // get the current settings of the AB select register 
    REG_PIOA_ABSR = tempo & 0xFFFFFCFF; // set PA8 and PA9 to peripheral A control 
    REG_PIOA_PDR = 0x0300L; // disable parallel I/O for PA8 and PA9 
    NVIC_EnableIRQ(UART_IRQn); // enable UART interrupts in NVIC 
    // now set up the UART 
    tempo = REG_PMC_PCSR0; // get the current settings of the peripheral clock register 0 
    REG_PMC_PCER0 = tempo | 0x0100L; // enable the UART clocks 
    REG_UART_CR = 0x0CL; // reset UART receiver and transmitter 
    REG_UART_MR = 0x0800L; // set to normal outputs with no parity 
    REG_UART_BRGR = 0x89L; // baud rate set to 38400 
    REG_UART_IDR = 0x1FBL; // disable all UART interrupts 
    REG_UART_IER = 0x0800L; // enable TXBUFE interrupt 
    REG_UART_CR = 0x50L; // enable UART receiver and transmitter 
    // set up the debug outputs 
    REG_PIOD_IDR = 0x03L; // disable interrupts on PD0 and PD1 
    REG_PIOD_PER = 0x03L; // enable parallel I/O for PD0 & PD1 
    REG_PIOD_OER = 0x03L; // set PD0 & PD1 output enabled 
    REG_PIOD_CODR = 0x03L; // drive PD0 & PD1 low 
} 

void loop() // run over and over 
{ 
    REG_PIOD_SODR = 0x01L; // drive PD0 high 
    delay(1); 
    REG_PIOD_CODR = 0x01L; // drive PD0 low 
    delay(1); 
} 

範圍輸出可以在http://www.iwanczuk.com/temp/scope1.png觀看。

在注視了一陣子並且沒有了解之後,我通過註釋行REG_UART_IER = 0x0800L; // enable TXBUFE interrupt來禁用TXBUFE中斷,PortD1的切換可見,但顯然沒有UART輸出(請參閱http://www.iwanczuk.com/temp/scope2.png)。看起來這兩者是相互排斥的,如果這是真的,那將是愚蠢的。我相信我錯過了一些東西,但我看不到或發現它是什麼。

我已閱讀SAM3X8E數據表,看看是否有任何明顯的我失蹤,如果有我不能看到它。我也做了我認爲相關的網絡搜索,但沒有找到解決方案。我也嘗試在端口A和端口D上使用通用輸出作爲兩個輸出,並且在兩個Arduino Due板上嘗試了這兩種輸出,兩者的結果都相似。

任何人有任何想法我可能會做錯什麼?提前致謝。

+0

UART_Handler如何被調用? – Greycon 2015-02-09 16:13:01

+0

似乎只要UART被使能,中斷處理程序就會被調用,並將第一個值加載到發送緩衝區中。之後,每次數據傳輸到發送移位寄存器時,TXBE中斷都會調用處理程序。這是我的假設,因爲我沒有在初始化中明確加載發送器,並且儘管如此也開始發送數據。 – Roman 2015-02-10 17:46:54

回答

0

那麼,我已經到了這個問題的底部。不知道這是最好的答案,但它是一個解決方案。它的長短是避免TXBE中斷。如果我使用TXEMPTY中斷,它可以正常工作。

Atmel數據手冊第168頁上的一行表示(中斷)「即使禁用它,中斷也可以進入掛起狀態」,所以我想知道TXBE的問題是因爲我之前沒有清除掛起的中斷,在ISR內部,所以我在ISR開始時加入了NVIC_ClearPendingIRQ(UART_IRQn);,並且在啓用TXBE中斷之前,(錯誤)行爲沒有改變。

TXEMPTY的操作對我來說還是有點奇怪,因爲看起來中斷是由發送移位寄存器產生的,而不是在變爲爲空時產生。如果您在未加載發送緩衝區的情況下啓用中斷,您將立即獲得中斷。有些人可能會喜歡這種「self = priming」行爲,但它並不適合我,我正在編寫我的發送例程,以使TXEMPTY中斷不會啓用,直到發送器裝載了要發送的第一個字節。

基於這個職位上Arduino的論壇:http://forum.arduino.cc/index.php?topic=186388.0我相信該個USART有一個類似的問題

希望這將有助於其他

0

我才意識到這可能是在源頭上真正的錯誤。我的問題。UART中斷寄存器描述在發送緩衝區爲空的情況下討論TXBUFE位,因此我的假設是,這是告訴我何時可以將另一個字節放入發送保持寄存器的位。然而,UART狀態寄存器說明TXBUFE位是「來自發送器PDC通道的緩衝器滿信號」。後者對這一點做了一個完全不同的傾斜。根據UART狀態寄存器描述,我需要查看的是TXRDY位!