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