摘 要: 詳細(xì)介紹了高效FIFO串口通信的基本原理和實(shí)現(xiàn)方法,并在兩臺(tái)基于ARM7TDMI微處理器的目標(biāo)機(jī)上,用FIFO串口通信模式實(shí)現(xiàn)了兩機(jī)之間的高效通信。整個(gè)工程分寄存器配置模塊、串口接收模塊、串口發(fā)送模塊和容錯(cuò)模塊。
關(guān)鍵詞: 嵌入式系統(tǒng);串口通信;FIFO;ARM;模塊
S3C44B0X(時(shí)鐘頻率為60 MHz)的UART單元提供2個(gè)獨(dú)立的異步串行I/O口,每個(gè)通信口均可工作于中斷或DMA模式。即UART能產(chǎn)生內(nèi)部中斷請(qǐng)求或DMA請(qǐng)求,在CPU和串行I/O口之間傳送數(shù)據(jù)。它支持高達(dá)115.2 Kb/s的傳輸速率,每1個(gè)UART通道包含了2個(gè)16位的分別用于接收和發(fā)送信號(hào)的先進(jìn)先出(FIFO)通道。S3C44B0X UART包括可編程波特率、紅外發(fā)送/接收、1個(gè)開(kāi)始位、1個(gè)或2個(gè)停止位、5/6/7/8位數(shù)據(jù)寬度和奇偶校驗(yàn)。每個(gè)UART包含1個(gè)波特率發(fā)生器、接收器、發(fā)送器和控制單元,其構(gòu)成如圖1所示[1]。
1 FIFO概述
1.1 FIFO概念
先入先出FIFO(First In First Out),即先被寫入到FIFO的數(shù)據(jù)將會(huì)先被讀出。它是一片用來(lái)緩存數(shù)據(jù)的存儲(chǔ)單元,可以把需要處理的數(shù)據(jù)先暫存在這片存儲(chǔ)單元中,在數(shù)據(jù)量達(dá)到一定數(shù)量時(shí)再集中處理,以提高系統(tǒng)性能。FIFO可以集成在芯片中,而當(dāng)系統(tǒng)需要的緩沖區(qū)較大時(shí),也可以用單獨(dú)的RAM實(shí)現(xiàn)。S3C44B0X串口收發(fā)器包含了16 B的FIFO和數(shù)據(jù)移位器,將要傳輸?shù)臄?shù)據(jù)寫進(jìn)FIFO,然后賦值到發(fā)送移位器,最后從發(fā)送的引腳移位發(fā)送出去,達(dá)到利用FIFO緩沖區(qū)高效通信的目的。
1.2 FIFO意義
FIFO是數(shù)據(jù)傳輸系統(tǒng)中極其重要的一環(huán),特別是在2個(gè)處于不同時(shí)鐘域的系統(tǒng)接口部分,F(xiàn)IFO的合理使用,不但能使接口處數(shù)據(jù)傳輸?shù)妮斎胼敵鏊俾蔬M(jìn)行有效的匹配,不使數(shù)據(jù)發(fā)生復(fù)寫、丟失和讀入無(wú)效數(shù)據(jù)的情況,而且還會(huì)有效地提高系統(tǒng)中數(shù)據(jù)的傳輸效率。使用FIFO進(jìn)行串口通信,較之傳統(tǒng)的串口通信有更高的效率。它將要發(fā)送和已經(jīng)接收的數(shù)據(jù)集中起來(lái)進(jìn)行操作,避免了頻繁的總線操作,減輕了CPU的負(fù)擔(dān)。因此,使得基于FIFO方式的串口通信目前應(yīng)用十分廣泛。
1.3 FIFO中斷請(qǐng)求
S3C44B0X的UART有7個(gè)狀態(tài)(Tx/Rx/Error)信號(hào):溢出錯(cuò)誤、奇偶錯(cuò)誤、幀錯(cuò)誤、斷點(diǎn)條件、接收FIFO/Buffer數(shù)據(jù)準(zhǔn)備就緒、發(fā)送FIFO/Buffer空和發(fā)送移位寄存器空,這些狀態(tài)信號(hào)由相應(yīng)的UART狀態(tài)寄存器(UTRSTATn/UERSTATn)聲明[1]。
當(dāng)處于接收錯(cuò)誤狀態(tài)時(shí),如果在控制寄存器(UCONn)中接收錯(cuò)誤狀態(tài)中斷使能位被置為1,則溢出錯(cuò)誤、奇偶校驗(yàn)錯(cuò)誤、幀錯(cuò)誤及斷點(diǎn)錯(cuò)誤,每1個(gè)作為1種錯(cuò)誤狀態(tài)都可發(fā)出錯(cuò)誤中斷請(qǐng)求。當(dāng)1個(gè)接收錯(cuò)誤狀態(tài)中斷請(qǐng)求被發(fā)現(xiàn)時(shí),引起中斷請(qǐng)求信號(hào)會(huì)被讀UERSTATn所識(shí)別。如果控制器中的接收模式被選定為中斷模式,則當(dāng)接收器從接收移位寄存器向接收FIFO傳輸數(shù)據(jù)時(shí),會(huì)激活接收FIFO的可引起接收中斷的“滿”狀態(tài)信號(hào)。同樣,如果控制器中的發(fā)送模式被選定為中斷模式,則當(dāng)發(fā)送器從發(fā)送FIFO向發(fā)送移位寄存器傳輸數(shù)據(jù)時(shí),可引起發(fā)送中斷的發(fā)送FIFO“空”狀態(tài)信號(hào)被激活。如表1所示。
2 FIFO串口通信的實(shí)現(xiàn)
FIFO重啟時(shí),輸入和輸出的指針都指向FIFO中的第1個(gè)存儲(chǔ)位置。對(duì)FIFO的每次寫入操作會(huì)使輸入指針指向FIFO的下1個(gè)存儲(chǔ)位置,相應(yīng)地每次讀取操作會(huì)使FIFO的輸出指針指向FIFO的上1個(gè)存儲(chǔ)位置。若指針需要從最后1個(gè)存儲(chǔ)位置移動(dòng)到第1個(gè)存儲(chǔ)位置,則FIFO會(huì)自動(dòng)實(shí)現(xiàn)這一過(guò)程而不需要任何對(duì)指針的重啟操作。FIFO內(nèi)部除了包含輸入和輸出端口之外,通常還有其他狀態(tài)標(biāo)志輸出,如空狀態(tài)和滿狀態(tài)。當(dāng)FIFO已空或者已滿時(shí),空狀態(tài)和滿狀態(tài)標(biāo)志位就會(huì)有相應(yīng)的輸出,即當(dāng)FIFO已空時(shí)不能進(jìn)行讀取操作,當(dāng)FIFO已滿時(shí)不能進(jìn)行寫入操作[2]。
2.1 配置特殊寄存器
為了使目標(biāo)系統(tǒng)能正常工作,必須配置相關(guān)的寄存器,如I/O口寄存器、串口控制寄存器和串口源/目的寄存器等。S3C44B0X有2個(gè)串口,這里以串口0為例,進(jìn)行相關(guān)寄存器的配置。
/*I/O口配置,定義各相關(guān)引腳功能和上拉電阻狀態(tài) */
rPCONC |=0xf0000000;
rPUPC |=0xc000;
rPCONE=(rPCONE &0x3ffeb)|0x28;
rPUPE |=0x6;
rPCONF=(rPCONF &0x3ff)+0x124800;
rPUPF |=0x1e0;
/* 定義串口0工作寄存器組 */
rULCON0=0x3; //正常模式,無(wú)奇偶校驗(yàn),1位停止位,8位數(shù)據(jù)位
rUCON0=0x245; //Rx為邊沿觸發(fā),Tx為電平觸發(fā),禁
//止超時(shí)中斷,產(chǎn)生接收錯(cuò)誤中斷,普通傳送、
//發(fā)送與接收為中斷或輪詢模式
rUFCON0=(2<<6)|(1<<4)|(6)|1; //FIFO啟動(dòng)需先復(fù)位
rUBRDIV0=(mclk/(baud*16)); //mclk為60000000,baud為115200
2.2 FIFO串口發(fā)送模塊
串口數(shù)據(jù)發(fā)送幀格式是可編程的,它包含1個(gè)開(kāi)始位,5~8個(gè)數(shù)據(jù)位,1個(gè)可選的奇偶位和1~2個(gè)停止位,這些都可以通過(guò)線控制寄存器(UCONn)來(lái)設(shè)置。發(fā)送器也能夠產(chǎn)生發(fā)送中止條件。中止條件迫使串口輸出保持在邏輯0狀態(tài),這種狀態(tài)保持超過(guò)1個(gè)傳輸幀的時(shí)間長(zhǎng)度。通常在1幀傳輸數(shù)據(jù)完整地傳輸完之后,再通過(guò)這個(gè)全0狀態(tài)將中止信號(hào)發(fā)送給對(duì)方。中止信號(hào)發(fā)送之后,傳送數(shù)據(jù)將持續(xù)地放入到輸出FIFO中。要發(fā)送的數(shù)據(jù)被存放在定義的字符串指針uart0TxStr 中,串口發(fā)送模塊通過(guò)讀該字符串中的字符進(jìn)行數(shù)據(jù)發(fā)送,核心源代碼如下:
void __irq Uart0_TxFifoInt(void)
{
/* 判斷FIFO發(fā)送緩沖區(qū)是否為滿或字符串結(jié)束 */
while( !(rUFSTAT0 & 0x200) && (*uart0TxStr !='\0'))
{
rUTXH0=*uart0TxStr++;
for(i=0;i<700;i++); //延遲,防止FIFO誤寫
}
rI_ISPC=BIT_UTXD0;
if(*uart0TxStr == '\0')
{
rINTMSK |= BIT_UTXD0;
rI_ISPC=BIT_UTXD0;
}
}
2.3 FIFO串口接收模塊
接收的數(shù)據(jù)幀格式與發(fā)送一樣都是可編程的。它包括了1個(gè)起始位,5~8個(gè)數(shù)據(jù)位,1個(gè)可選的奇偶校驗(yàn)位和1~2個(gè)停止位,這些都可以通過(guò)線控制寄存器(UCONn)來(lái)設(shè)置。接收器還可以檢測(cè)到溢出錯(cuò)誤、奇偶校驗(yàn)錯(cuò)誤、幀錯(cuò)誤和中止?fàn)顩r,每種情況下都會(huì)將1個(gè)錯(cuò)誤標(biāo)志置位。
(1)溢出錯(cuò)誤表示新的數(shù)據(jù)已經(jīng)覆蓋了舊的數(shù)據(jù),因?yàn)榕f的數(shù)據(jù)沒(méi)有及時(shí)被讀入。
(2)奇偶校驗(yàn)錯(cuò)誤表示接收器檢測(cè)到了意料之外的奇偶校驗(yàn)結(jié)果。
(3)幀錯(cuò)誤表示接收到的數(shù)據(jù)沒(méi)有有效的停止位。
(4)中止?fàn)顩r表示RxDn的輸入被保持為0狀態(tài)超過(guò)了1個(gè)幀傳輸?shù)臅r(shí)間[3]。
(5)在FIFO模式下接收FIFO不為空,但接收器已經(jīng)在3個(gè)字時(shí)間內(nèi)沒(méi)有接收到任何數(shù)據(jù),就認(rèn)為發(fā)生了接收超時(shí)狀況。
接收模塊將數(shù)據(jù)從接收移位寄存器中讀出后,首先被存儲(chǔ)到接收緩存數(shù)組keyBuf[ ]中。變量keyBufWrPt和keyBufRdPt指向緩存數(shù)組中當(dāng)前寫數(shù)據(jù)和讀數(shù)據(jù),當(dāng)接收模塊往緩存數(shù)組中寫入1個(gè)字節(jié)后,keyBufWrPt加1;當(dāng)Uart_IntGetKey從緩存數(shù)組中讀出1個(gè)字節(jié)后,keyBufRdPt加1。兩變量最大值為KEY_LEN,超過(guò)最大值時(shí)置零。接收模塊的核心代碼如下[4]:
/* 接收模塊將移位寄存器中的數(shù)據(jù)讀出到接收緩存數(shù)組中 */
void __irq Uart0_RxFifoInt(void)
{
rI_ISPC=BIT_URXD0;
if(rUFSTAT0==0)
Uart_Printf("time out\n");
while( (rUFSTAT0&0xf) >0 ) //循環(huán)直到FIFO
//發(fā)送緩沖區(qū)為空
{
keyBuf[keyBufWrPt++]=rURXH0; //讀取接收緩沖區(qū)數(shù)據(jù)存入緩存數(shù)組
if(keyBufWrPt==KEY_BUFLEN)
keyBufWrPt=0;
}
}
/* 定義1個(gè)函數(shù)從接收緩存數(shù)組中讀取數(shù)據(jù) */
char Uart_IntGetkey(void)
{
if(keyBufRdPt==KEY_BUFLEN)
keyBufRdPt=0;
while(keyBufWrPt==keyBufRdPt);//等待直到FIFO被觸發(fā)
return keyBuf[keyBufRdPt++];
}
2.4 FIFO容錯(cuò)模塊
除了接收FIFO寄存器之外,UART還具有1個(gè)狀態(tài)FIFO。狀態(tài)FIFO表示了在FIFO寄存器中,哪一個(gè)數(shù)據(jù)被毫無(wú)錯(cuò)誤地接收。假設(shè)UART的FIFO連續(xù)接收到A、B、C、D、E字符,并且在接收B字符時(shí)發(fā)生了幀錯(cuò)誤(即該字符沒(méi)有停止位),在接收D字符時(shí)發(fā)生了奇偶校驗(yàn)錯(cuò)。雖然UART錯(cuò)誤發(fā)生了,但不會(huì)產(chǎn)生錯(cuò)誤中斷,因?yàn)楹绣e(cuò)誤的字符還沒(méi)有被CPU讀取。當(dāng)字符被讀出時(shí)錯(cuò)誤中斷才會(huì)發(fā)生,而且只有在讀出URXHn和UERSTATn寄存器后,F(xiàn)IFO錯(cuò)誤狀態(tài)寄存器才會(huì)被清除[5]。容錯(cuò)模塊核心代碼如下[6]。
void __irq Uart0_RxFifoErrorInt(void)
{
rI_ISPC=BIT_UERR01;
Uart_Printf("UERSTAT0=0x%x\n",rUERSTAT0& 0xf);
while( (rUFSTAT0&0xf) >0 )
{
keyBuf[keyBufWrPt++]=rURXH0;
if(keyBufWrPt==KEY_BUFLEN);
keyBufWrPt=0;
}
}
3 實(shí)驗(yàn)結(jié)果
本實(shí)驗(yàn)在S3C44B0X和ADS1.2平臺(tái)上實(shí)現(xiàn),取得了預(yù)期的效果。在同等條件下(忽略溫度、電壓等外部因素變化),在帶FIFO(FIFO)和不帶FIFO(Non-FIFO)時(shí)發(fā)送和接收所花時(shí)間如表2所示。
以傳輸4 KB數(shù)據(jù)為例,由表2可知,使用FIFO時(shí),發(fā)送和接收分別節(jié)省0.547 076 s和0.042 832 s時(shí)間。假定傳輸1 bit的數(shù)據(jù)用時(shí)為θs,傳輸數(shù)據(jù)量為n,則可知使用FIFO和不使用FIFO兩種情況下的用時(shí)差為15nθ/16s。由此可見(jiàn),當(dāng)傳輸數(shù)據(jù)量n越大時(shí),采用FIFO的串口傳輸模式的用時(shí)越少、優(yōu)越性越明顯。這也顯示了FIFO在串口傳輸較大數(shù)據(jù)量的工程應(yīng)用中的重要性和必要性。
在串口通信應(yīng)用越來(lái)越廣的背景下,提高串口通信速度顯得格外重要。本文以S3C44B0X微處理器為平臺(tái),介紹的基于FIFO的串口雙機(jī)通信的原理和實(shí)現(xiàn)方法,該方法同時(shí)也適用于其他配置FIFO緩沖區(qū)的微處理器,具有很強(qiáng)的適用性和通用性,在學(xué)習(xí)、研究的同時(shí),也為工程應(yīng)用中的串口通信提供了參考模型。
參考文獻(xiàn)
[1] 田澤.嵌入式系統(tǒng)開(kāi)發(fā)與應(yīng)用[M].北京:北京航空航天大學(xué)出版社,2005.
[2] Samsung. S3C44B0X datasheet[EB/OL]. http://pdf1.alldatasheet.com/datasheet-pdf/view/84253/SAMSUNG/S3C44-B0X.html,2003.
[3] 馬忠梅,英惠.ARM嵌入式處理器結(jié)構(gòu)與應(yīng)用基礎(chǔ)(第2版)[M].北京:北京航空航天大學(xué)出版社,2007.
[4] 嚴(yán)蔚敏,吳偉民.數(shù)據(jù)結(jié)構(gòu):C語(yǔ)言版[M].北京:清華大學(xué)出版社,1996.
[5] 胥靜.嵌入式系統(tǒng)設(shè)計(jì)與開(kāi)發(fā)實(shí)例詳解:基于ARM的應(yīng)用[M].北京:北京航空航天大學(xué)出版社,2005.
[6] 王宇行.ARM程序分析與設(shè)計(jì)[M].北京:北京航空航天大學(xué)出版社,2008.