這篇將示範如何使用 USART 傳輸資料。
首先,先看使用 Arduino 的版本:
程式很簡單,就不解釋了。接著讓我們改用直接控制 USART 暫存器來傳輸資料。
非中斷版本
底下這支程式會在 Serial Port 印出 "Hello World" 訊息:
mySerial_begin() 函式用來開啟 Serial Port,主要進行下列通訊設定:
- 透過 UBBR0H 和 UBBR0L 暫存器設定通訊速率
- 透過 UCSR0B 啟用 transmitter 和 receiver,並且不使用中斷
- 透過 UCSR0C 設定 Frame format 為 N, 8, 1
serial_putchar() 會將一個字元放到 UDR0 等待傳送,我們必須等到 UDRE (USART Data Register Empty) 旗號豎起來時才能把資料放到 UDR0,其中 loop_until_bit_is_set 是一個巨集指令,它其實只是個簡單的迴圈:
下圖是程式的執行結果:
中斷版本
底下則是使用中斷的版本:
mySerial_begin() 函式沒有變動。
當呼叫 interrupt_on() 時,會立即發生 USART Data Register Empty 中斷,CPU 就會跳到 ISR 執行。
程式加了 USART_UDRE_vect 的 ISR 用來處理中斷,它的邏輯是從 message 取出字元放到 UDR0 去傳送,直到遇到字串的 NULL byte 為止,當資料都送完時,就呼叫 interrupt_off() 關閉中斷。
Cooper好~~~
回覆刪除請問
UBRR0H = (unsigned char)(baud_setting >> 8);
UBRR0L = (unsigned char)baud_setting;
這兩行的語法還有意思是什麼?
這部分我不太了解....請Cooper幫忙解答~~
謝謝~~~
以這行而言:
回覆刪除UBRR0H = (unsigned char)(baud_setting >> 8);
(baud_setting >> 8) 是右移 8 個位元。假如 baud_setting 是:
0000 0001 0000 1111
右移 8 個位元之後,結果將會是:
0000 0000 0000 0001
然後結果會轉成 unsigned char 變成只有一個 byte:
0000 00001
UBRR0H 跟 UBRR0L 這兩個暫存器是用來設定 baud rate 的
(見這裏的說明 http://coopermaa2nd.blogspot.tw/2011/07/5-usart.html)
公式是:
ubbr 設定值 = (F_CPU/16/baud rate) – 1
舉例:
假如要設成 9600,那麼根據公式:
(16000000/16/9600) – 1
得 103,所以:
UBRR0H = (unsigned char) (103 >> 8);
UBRR0L = (unsigned char) 103;
得 UBRR0L 是 103,而 UBRR0H 則是 0 (因為 103 右移 8 個位元後結果為 0)
一般情況下,UBRR0H 通常都是 0,但是在某些 baud rate 設定下,公式算出來的結果會超過一個位元組(超過 255 ),這時光靠 UBRR0L 就不夠表示,所以就會用到 UBRR0H。
比如 2400 的 baud rate,根據公式
(16000000/16/2400) – 1
得 416,所以:
UBRR0H = (unsigned char) (416 >> 8);
UBRR0L = (unsigned char) 416;
得 UBRR0H 為 0000 0001 (416 右移 8 個位元後結果為 1)
而 UBRR0L 則為 160 (1010 0000),因為 416 轉成 unsighed char 後,超過 256 的部份就被截掉了
希望可以解答你的疑惑
超級清楚!!! 謝謝~~~~~
回覆刪除