關于模擬串口的波特率的分析研究
在用單片機開發各種嵌入式應用系統中,由于異步串行通訊連接簡單,因而成為經常用到的一種通信模式,很多應用中還要求實現多路異步串行通信。為了提高系統的性能價格比,就要求設計工程師用軟件增加實現一路或多路異步串行通信。本文即是對模擬串口的波特率做出的一點分析。
首先簡單的介紹一下串行異步通訊的數據格式定義,發送或接收一個完整的字節信息,必須有“起始位”、“若干數據位”、“奇偶校驗位”和“停止位”;定義每位信息的時間寬度——每秒發送的信息位個數,即為“波特率”。本文附帶的模擬串口源程序采用數據幀的格式為 1位起始位(低電平),8位數據位(先低位在高位),1位停止位(高電平),且在線路空閑狀態時總是保持為高電平。當在11M晶振時鐘頻率下,采用波特率為9600或19200時。該模擬串口都可以無誤差的進行傳輸,具體分析后面進行。
參照源程序,我們知道,在這個模擬串口設計中,模擬的是單片機串行異步通訊方式1,由P1^0做接收端,P1^1做發送端,通過定時器1定時溢出中斷來確定每位數據的時間,由StartBitOn()函數不斷查詢接收端的狀態,當出現低電平(即起始位)的時候,調用接收程序,接收發送的數據。
針對以下附帶的源程序分析知,PGetChar(),PSendChar()都是通過移位方式來接收數據,每接收一位數據,需要定時器溢出產生中斷一次,故要得到一幀的數據,就必須經過10個數據位的時間才能完成,同樣的,在模擬串口的發送端,要完整的發送一幀數據也要經過10個數據位的時間。因而在如下連接時,引出了以下的問題。
當RS232單次發送一個字符時,可以正常接收和發送回RS232。
當RS232連續發送一串字符時,通過模擬串口返回給RS232的字符只有原來的一半。如發送1234567890這樣一個字符串時,接收的字符為13579。
那為什么在單獨發送一個字符是不會丟失,而連續發送時就只有原來的一半了呢!
__________________________________________
||||
||||
| PC|---------->| PGetChar()|
|RS232|||MCU|
|||V|
||<----------| PSendChar()|
--------------------------------------------
源程序:
/**********************************************
IO 口模擬232串行異步通訊程序
**********************************************/
#include
sbit BT_SND =P1^1;
sbit BT_REC =P1^0;
#define F_TM F0//自定義標志位,作為中斷標志位
#define TIMER0_ENABLETL0=TH0; TR0=1;//TR0 = 1,啟動T
#define TIMER0_DISABLE TR0=0;
// Acc 累加器做發送的移位寄存器
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;
//定時器計數器0的中斷
void IntTimer0() interrupt 1
{
F_TM=1;
}
//發送一個字符
//數據格式一個啟動位(0),8數據位,一個停止位(1)
void PSendChar(unsignedCHARGetch)
{
ACC=Getch;
F_TM=0;
BT_SND=0; //啟動位
TIMER0_ENABLE; //記數器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
}
//接收一個字符
unsignedCHARPGetChar()
{
unsignedCHARrch,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()
{
unsignedCHARGetch;
TMOD=0x22; /*定時器1為工作模式2(8位自動重裝),0為模式2(8位
自動重裝) */
PCON=00;
TR0=0; //在發送或接收才開始使用
TF0=0;
TH0=(256-96); //9600bps 就是 1000000/9600=104.167微秒 執行的
//時間是104.167*11.0592/12= 96
TL0=TH0;
ET0=1;//定時器/記數器T0的溢出中斷允許位,ET,允 許中斷
EA=1;
while(1)
{
if(StartBitOn())
{
Getch=PGetChar();
PSendChar(Getch);
}
}
}
實驗環境:
串口調試助手軟件
AT89S51單片機及相應的硬件設備
評論