|
在用單片機(jī)開發(fā)各種嵌入式應(yīng)用系統(tǒng)中,由于異步串行通訊連接簡單,因而成為經(jīng)常用到的一種通信模式,很多應(yīng)用中還要求實現(xiàn)多路異步串行通信。為了提高系統(tǒng)的性能價格比,就要求設(shè)計工程師用軟件增加實現(xiàn)一路或多路異步串行通信。本文即是對模擬串口的波特率做出的一點分析。 首先簡單的介紹一下串行異步通訊的數(shù)據(jù)格式定義,發(fā)送或接收一個完整的字節(jié)信息,必須有“起始位”、“若干數(shù)據(jù)位”、“奇偶校驗位”和“停止位”;定義每位信息的時間寬度——每秒發(fā)送的信息位個數(shù),即為“波特率”。本文附帶的模擬串口源程序采用數(shù)據(jù)幀的格式為 1位起始位(低電平),8位數(shù)據(jù)位(先低位在高位),1位停止位(高電平),且在線路空閑狀態(tài)時總是保持為高電平。當(dāng)在11M晶振時鐘頻率下,采用波特率為9600或19200時。該模擬串口都可以無誤差的進(jìn)行傳輸,具體分析后面進(jìn)行。 參照源程序,我們知道,在這個模擬串口設(shè)計中,模擬的是單片機(jī)串行異步通訊方式1,由P1^0做接收端,P1^1做發(fā)送端,通過定時器1定時溢出中斷來確定每位數(shù)據(jù)的時間,由StartBitOn()函數(shù)不斷查詢接收端的狀態(tài),當(dāng)出現(xiàn)低電平(即起始位)的時候,調(diào)用接收程序,接收發(fā)送的數(shù)據(jù)。 針對以下附帶的源程序分析知,PGetChar(),PSendChar()都是通過移位方式來接收數(shù)據(jù),每接收一位數(shù)據(jù),需要定時器溢出產(chǎn)生中斷一次,故要得到一幀的數(shù)據(jù),就必須經(jīng)過10個數(shù)據(jù)位的時間才能完成,同樣的,在模擬串口的發(fā)送端,要完整的發(fā)送一幀數(shù)據(jù)也要經(jīng)過10個數(shù)據(jù)位的時間。因而在如下連接時,引出了以下的問題。 當(dāng)RS232單次發(fā)送一個字符時,可以正常接收和發(fā)送回RS232。 當(dāng)RS232連續(xù)發(fā)送一串字符時,通過模擬串口返回給RS232的字符只有原來的一半。如發(fā)送1234567890這樣一個字符串時,接收的字符為13579。 那為什么在單獨發(fā)送一個字符是不會丟失,而連續(xù)發(fā)送時就只有原來的一半了呢! ____________ ______________________________ | | | | | | | | | PC |---------->| PGetChar() | | RS232| | | MCU | | | | V | | |<----------| PSendChar() | ------------- ------------------------------- 源程序: /********************************************** IO 口模擬232串行異步通訊程序
**********************************************/ #include <reg51.h> sbit BT_SND =P1^1; sbit BT_REC =P1^0;
#define F_TM F0 //自定義標(biāo)志位,作為中斷標(biāo)志位 #define TIMER0_ENABLE TL0=TH0; TR0=1;//TR0 = 1,啟動T #define TIMER0_DISABLE TR0=0;
// Acc 累加器做發(fā)送的移位寄存器 sbit ACC0 = ACC^0; sbit ACC1 = ACC^1; sbit ACC2 = ACC^2; sbit ACC3 = ACC^3; sbit ACC4 = ACC^4; sbit ACC5 = ACC^5; sbit ACC6 = ACC^6; sbit ACC7 = ACC^7;
//定時器計數(shù)器0的中斷 void IntTimer0() interrupt 1 { F_TM=1; } //發(fā)送一個字符 //數(shù)據(jù)格式一個啟動位(0),8數(shù)據(jù)位,一個停止位(1) void PSendChar(unsigned char Getch) { ACC=Getch; F_TM=0; BT_SND=0; //啟動位 TIMER0_ENABLE; //記數(shù)器0啟動 while(!F_TM) ; BT_SND=ACC0; //先送出低位 F_TM=0; while(!F_TM) ; BT_SND=ACC1; F_TM=0; while(!F_TM) ; BT_SND=ACC2; F_TM=0; while(!F_TM); BT_SND=ACC3; F_TM=0; while(!F_TM); BT_SND=ACC4; F_TM=0; while(!F_TM); BT_SND=ACC5; F_TM=0; while(!F_TM); BT_SND=ACC6; F_TM=0; while(!F_TM); BT_SND=ACC7; F_TM=0; while(!F_TM); BT_SND=1; F_TM=0; while(!F_TM); TIMER0_DISABLE; //停止timer } //接收一個字符 unsigned char PGetChar() { unsigned char rch,ii; TIMER0_ENABLE; F_TM=0; ii=0; rch=0; while(!F_TM); //等過起始位
while(ii<8) { rch>>=1; if(BT_REC) { rch|=0x80; } ii++; F_TM=0; while(!F_TM);
} F_TM=0; while(!F_TM) { if(BT_REC) { break; } } TIMER0_DISABLE; //停止timer return rch;
} //檢查是不是有起始位 bit StartBitOn() { return (BT_REC==0);
} void main() { unsigned char Getch;
TMOD=0x22; /*定時器1為工作模式2(8位自動重裝),0為模式2(8位 自動重裝) */ PCON=00; TR0=0; //在發(fā)送或接收才開始使用 TF0=0; TH0=(256-96); //9600bps 就是 1000000/9600=104.167微秒 執(zhí)行的 //時間是104.167*11.0592/12= 96 TL0=TH0; ET0=1;//定時器/記數(shù)器T0的溢出中斷允許位,ET,允 許中斷 EA=1; while(1) { if(StartBitOn()) { Getch=PGetChar(); PSendChar(Getch); } } } 實驗環(huán)境: 串口調(diào)試助手軟件 AT89S51單片機(jī)及相應(yīng)的硬件設(shè)備 win2000操作系統(tǒng) 原因分析如下: PC的RS232像單片機(jī)發(fā)送1234567890字符串時,是連續(xù)一次發(fā)送的。當(dāng)StartBitOn()檢測到低電平起始位時,運行Getch=PGetChar()函數(shù),顯然上面說過要得到一幀的數(shù)據(jù),就必須經(jīng)過10個數(shù)據(jù)位的時間,同樣運行PSendChar(Getch)函數(shù)時,也必須經(jīng)過10個數(shù)據(jù)位的時間,且都是在忽略單片機(jī)本身執(zhí)行指令的時間得到的。因而在當(dāng)單片機(jī)接收了一個數(shù)據(jù)在接收下一位數(shù)據(jù)期間,必須至少消耗20個數(shù)據(jù)位的時間,等它在開始檢測起始位時候,已經(jīng)傳輸?shù)降谌齻字符了,因而才會出現(xiàn)第上面的情況,當(dāng)發(fā)送1234567890,而接收的字符是13579的原因。也就才會出現(xiàn)了很多工程師朋友們會對用軟件實現(xiàn)的UART在可靠性和效率方面持懷疑態(tài)度的現(xiàn)象 if(StartBitOn()) { Getch=PGetChar(); //采用移位方式要消耗10個數(shù)據(jù)位的時間 PSendChar(Getch); //采用移位方式要消耗10個數(shù)據(jù)位的時間 }
BT_REC 接收到的電平: 第1幀數(shù)據(jù)(10個數(shù)據(jù)位)第2幀(10個數(shù)據(jù)位)第3幀(10個起始位)
起始位1 起始位2 起始位3 參照上面的數(shù)據(jù)格式示意圖知,當(dāng)單片機(jī)StartBitOn()檢測到起始位1并完成相應(yīng)的接收轉(zhuǎn)發(fā)Getch=PGetChar(); PSendChar(Getch),在進(jìn)行下一次檢測時,檢測到的下一個起始位就是起始位3了。
綜合上面分析可得出以下結(jié)論,在用軟件模擬串行通訊時候,是以時間來模擬硬件設(shè)備的,用軟件實現(xiàn)的UART的效率肯定沒有辦法和硬件UART比,在上敘連接時候,實際接收的數(shù)據(jù)確實只能有原來的一半,因為它是連續(xù)進(jìn)行接收和發(fā)送兩項工作的,但在實際應(yīng)用中,可以通過一定的手段,比如先一次接收好PC所發(fā)送過來的所有數(shù)據(jù),保存在預(yù)先設(shè)置的緩沖區(qū)里,稍后再去進(jìn)行發(fā)送的工作,這樣在接收的時候消耗的時間就只有10個數(shù)據(jù)位,在接收過程中不會丟失數(shù)據(jù),能正確接收到所發(fā)送的所有字符。 |