AVR單片機(學習ing)-ATMEGA16的USART與PC機串行通信
7、數據發送—USART發送器
置位UCSRB 寄存器的發送允許位TXEN 將使能USART 的數據發送。使能后TxD 引腳
的通用I/O 功能即被USART 功能所取代,成為發送器的串行輸出引腳。發送數據之前要
設置好波特率、工作模式與幀結構。如果使用同步發送模式,施加于XCK 引腳上的時鐘
信號即為數據發送的時鐘。
1)發送5 到8 位數據位的幀
將需要發送的數據加載到發送緩存器將啟動數據發送。加載過程即為CPU 對UDR 寄存
器的寫操作。當移位寄存器可以發送新一幀數據時,緩沖的數據將轉移到移位寄存器。當
移位寄存器處于空閑狀態( 沒有正在進行的數據傳輸),或前一幀數據的最后一個停止位
傳送結束,它將加載新的數據。一旦移位寄存器加載了新的數據,就會按照設定的波特率
完成數據的發送
以下程序給出一個對UDRE 標志采用輪詢方式發送數據的例子。當發送的數據少于8 位
時,寫入UDR 相應位置的高幾位將被忽略。當然,執行本段代碼之前首先要初始化
USART。在匯編代碼中要發送的數據存放于R16。
void USART_Transmit( unsigned char data )
{
while ( !( UCSRA & (1<
UDR = data;
}
2)發送9位數據的幀
TXB8,然后再將低8位數據寫入發送數據寄存器UDR。以下程序給出發送9位數據的數據
幀例子。在匯編代碼中要發送的數據存放在R17:R16 寄存器中。
void USART_Transmit( unsigned int data )
{
while ( !( UCSRA & (1<
UCSRB &= ~(1<
UCSRB |= (1<
UDR = data;
}
第9 位數據在多機通信中用于表示地址幀,在同步通信中可以用于協議處理。
3)傳送標志位與中斷
USART 發送器有兩個標志位:USART 數據寄存器空標志UDRE 及傳輸結束標志TXC,兩
個標志位都可以產生中斷。
數據寄存器空UDRE 標志位表示發送緩沖器是否可以接受一個新的數據。該位在發送緩
沖器空時被置"1” ;當發送緩沖器包含需要發送的數據時清零。為與將來的器件兼容,寫
UCSRA 寄存器時該位要寫"0”。
當UCSRB 寄存器中的數據寄存器空中斷使能位UDRIE 為"1” 時,只要UDRE 被置位(
且全局中斷使能),就將產生USART 數據寄存器空中斷請求。對寄存器UDR 執行寫操作
將清零UDRE。當采用中斷方式的傳輸數據時,在數據寄存器空中斷服務程序中必須寫一
個新的數據到UDR 以清零UDRE ;或者是禁止數據寄存器空中斷。否則一旦該中斷程序
結束,一個新的中斷將再次產生。
當整個數據幀移出發送移位寄存器,同時發送緩沖器中又沒有新的數據時,發送結束標志
TXC 置位。TXC 在傳送結束中斷執行時自動清零,也可在該位寫"1” 來清零。TXC 標志位
對于采用如RS-485 標準的半雙工通信接口十分有用。在這些應用里,一旦傳送完畢,應
用程序必須釋放通信總線并進入接收狀態。
當UCSRB 上的發送結束中斷使能位TXCIE 與全局中斷使能位均被置為"1” 時,隨著TXC
標志位的置位, USART 發送結束中斷將被執行。一旦進入中斷服務程序, TXC 標志位
即被自動清零,中斷處理程序不必執行TXC 清零操作。
4)奇偶校驗產生電路
奇偶校驗產生電路為串行數據幀生成相應的校驗位。校驗位使能(UPM1 = 1) 時,發送控
制邏輯電路會在數據的最后一位與第一個停止位之間插入奇偶校驗位。
5)禁止發送器
TXEN 清零后,只有等到所有的數據發送完成后發送器才能夠真正禁止,即發送移位寄存
器與發送緩沖寄存器中沒有要傳送的數據。發送器禁止后,TxD引腳恢復其通用I/O功能。
8、數據接收—USART接收器
置位UCSRB 寄存器的接收允許位(RXEN) 即可啟動USART 接收器。接收器使能后RxD
的普通引腳功能被USART 功能所取代,成為接收器的串行輸入口。進行數據接收之前首
先要設置好波特率、操作模式及幀格式。 如果使用同步操作, XCK 引腳上的時鐘被用為
傳輸時鐘。
1)以5 到8 個數據位的方式接收數據幀
一旦接收器檢測到一個有效的起始位,便開始接收數據。起始位后的每一位數據都將以所
設定的波特率或XCK 時鐘進行接收,直到收到一幀數據的第一個停止位。接收到的數據
被送入接收移位寄存器。第二個停止位會被接收器忽略。 接收到第一個停止位后,接收移
位寄存器就包含了一個完整的數據幀。這時移位寄存器中的內容將被轉移到接收緩沖器
中。通過讀取UDR 就可以獲得接收緩沖器的內容的。
以下程序給出一個對RXC 標志采用輪詢方式接收數據的例子。當數據幀少于8 位時,從
UDR 讀取的相應的高幾位為0。當然,執行本段代碼之前首先要初始化USART。
unsigned char USART_Receive( void )
{
while ( !(UCSRA & (1<
return UDR;
}
在讀緩沖器并返回之前,函數通過檢查RXC 標志來等待數據送入接收緩沖器。
2)以9 個數據位的方式接收幀
如果設定了9 位數據的數據幀(UCSZ=7),在從UDR 讀取低8 位之前必須首先讀取寄存
器UCSRB 的RXB8 以獲得第9 位數據。這個規則同樣適用于狀態標志位FE、DOR 及
UPE。狀態通過讀取UCSRA獲得,數據通過UDR獲得。讀取UDR存儲單元會改變接收緩
沖器FIFO 的狀態,進而改變同樣存儲在FIFO 中的TXB8、 FE、DOR 及UPE 位。
接下來的代碼示例展示了一個簡單的USART接收函數,說明如何處理9位數據及狀態位。
unsigned int USART_Receive( void )
{
unsigned char status, resh, resl;
while ( !(UCSRA & (1<
status = UCSRA;
resh = UCSRB;
resl = UDR;
if ( status & (1<
resh = (resh >> 1) & 0x01;
return ((resh << 8) | resl);
}
上述例子在進行任何計算之前將所有的I/O寄存器的內容讀到寄存器文件中。 這種方法優
化了對接收緩沖器的利用。它盡可能早地釋放了緩沖器以接收新的數據。、
3)接收結束標志及中斷
USART 接收器有一個標志用來指明接收器的狀態。
接收結束標志(RXC) 用來說明接收緩沖器中是否有未讀出的數據。 當接收緩沖器中有未
讀出的數據時,此位為1,當接收緩沖器空時為0( 即不包含未讀出的數據)。如果接收器
被禁止(RXEN = 0),接收緩沖器會被刷新,從而使RXC 清零。
置位UCSRB 的接收結束中斷使能位(RXCIE) 后,只要RXC 標志置位( 且全局中斷只能
) 就會產生USART 接收結束中斷。使用中斷方式進行數據接收時,數據接收結束中斷服
務程序程序必須從UDR 讀取數據以清RXC 標志,否則只要中斷處理程序一結束,一個
新的中斷就會產生。
4)接受錯誤標志
USART 接收器有三個錯誤標志::幀錯誤(FE)、數據溢出(DOR) 及奇偶校驗錯(UPE)。它
們都位于寄存器UCSRA。錯誤標志與數據幀一起保存在接收緩沖器中。由于讀取UDR
會改變緩沖器, UCSRA 的內容必須在讀接收緩沖器(UDR) 之前讀入。錯誤標志的另一
個同一性是它們都不能通過軟件寫操作來修改。 但是為了保證與將來產品的兼容性,對
執行寫操作是必須對這些錯誤標志所在的位置寫"0“。所有的錯誤標志都不能產生中斷。
幀錯誤標志(FE) 表明了存儲在接收緩沖器中的下一個可讀幀的第一個停止位的狀態。停
止位正確( 為1) 則FE 標志為0,否則FE 標志為1。 這個標志可用來檢測同步丟失、傳
輸中斷,也可用于協議處理。UCSRC 中USBS 位的設置不影響FE 標志位,因為除了第
一位,接收器忽略所有其他的停止位。 為了與以后的器件相兼容,寫UCSRA 時這一位必
須置0。
數據溢出標志(DOR) 表明由于接收緩沖器滿造成了數據丟失。當接收緩沖器滿( 包含了
兩個數據),接收移位寄存器又有數據,若此時檢測到一個新的起始位,數據溢出就產生
了。DOR 標志位置位即表明在最近一次讀取UDR 和下一次讀取UDR 之間丟失了一個或
更多的數據幀。 為了與以后的器件相兼容,寫UCSRA 時這一位必須置0。當數據幀成功
地從移位寄存器轉入接收緩沖器后, DOR 標志被清零。
奇偶校驗錯標志 (UPE) 指出,接收緩沖器中的下一幀數據在接收時有奇偶錯誤。 如果不
使能奇偶校驗,那么UPE 位應清零。為了與以后的器件相兼容,寫UCSRA 時這一位必
須置0。
5)奇偶校驗器
奇偶校驗模式位UPM1置位將啟動奇偶校驗器。校驗的模式(偶校驗還是奇校驗)由UPM0
確定。奇偶校驗使能后,校驗器將計算輸入數據的奇偶并把結果與數據幀的奇偶位進行比
較。 校驗結果將與數據和停止位一起存儲在接收緩沖器中。這樣就可以通過讀取奇偶校
驗錯誤標志位(UPE) 來檢查接收的幀中是否有奇偶錯誤。
如果下一個從接收緩沖器中讀出的數據有奇偶錯誤,并且奇偶校驗使能(UPM1 = 1),則
UPE 置位。直到接收緩沖器(UDR) 被讀取,這一位一直有效。
6)禁止接收器
與發送器對比,禁止接收器即刻起作用。正在接收的數據將丟失。禁止接收器(RXEN 清
零) 后,接收器將不再占用RxD 引腳;接收緩沖器FIFO 也會被刷新。緩沖器中的數據將
丟失。
7)刷新接收緩沖器
禁止接收器時緩沖器FIFO 被刷新,緩沖器被清空。導致未讀出的數據丟失。如果由于出
錯而必須在正常操作下刷新緩沖器,則需要一直讀取UDR 直到RXC 標志清零。下面的
代碼展示了如何刷新接收緩沖器。
void USART_Flush( void )
{
unsigned char dummy;
while ( UCSRA & (1<
評論