新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 51單片機(jī)串口問(wèn)題

51單片機(jī)串口問(wèn)題

作者: 時(shí)間:2016-11-25 來(lái)源:網(wǎng)絡(luò) 收藏
51單片機(jī)的串口,是個(gè)全雙工的串口,發(fā)送數(shù)據(jù)的同時(shí),還可以接收數(shù)據(jù)。
當(dāng)串行發(fā)送完畢后,將在標(biāo)志位 TI 置 1,同樣,當(dāng)收到了數(shù)據(jù)后,也會(huì)在 RI 置 1。
無(wú)論 RI 或 TI 出現(xiàn)了 1,只要串口中斷處于開(kāi)放狀態(tài),單片機(jī)都會(huì)進(jìn)入串口中斷處理程序。
在中斷程序中,要區(qū)分出來(lái)究竟是發(fā)送引起的中斷,還是接收引起的中斷,然后分別進(jìn)行處理。
看到過(guò)一些書(shū)籍和文章,在串口收、發(fā)數(shù)據(jù)的處理方法上,很多人都有不妥之處。
接收數(shù)據(jù)時(shí),基本上都是使用“中斷方式”,這是正確合理的。
即:每當(dāng)收到一個(gè)新數(shù)據(jù),就在中斷函數(shù)中,把 RI 清零,并用一個(gè)變量,通知主函數(shù),收到了新數(shù)據(jù)。
發(fā)送數(shù)據(jù)時(shí),很多的程序都是使用的“查詢方式”,就是執(zhí)行 while(TI ==0); 這樣的語(yǔ)句來(lái)等待發(fā)送完畢。
這時(shí),處理不好的話,就可能帶來(lái)問(wèn)題。
看了一些網(wǎng)友編寫(xiě)的程序,發(fā)現(xiàn)有如下幾條容易出錯(cuò):
1.有人在發(fā)送數(shù)據(jù)之前,先關(guān)閉了串口中斷!等待發(fā)送完畢后,再打開(kāi)串口中斷。
這樣,在發(fā)送數(shù)據(jù)的等待期間內(nèi),如果收到了數(shù)據(jù),將不能進(jìn)入中斷函數(shù),也就不會(huì)保存的這個(gè)新收到的數(shù)據(jù)。
這種處理方法,就會(huì)遺漏收到的數(shù)據(jù)。
2.有人在發(fā)送數(shù)據(jù)之前,并沒(méi)有關(guān)閉串口中斷,當(dāng) TI = 1 時(shí),是可以進(jìn)入中斷程序的。
但是,卻在中斷函數(shù)中,將 TI 清零!
這樣,在主函數(shù)中的while(TI ==0);,將永遠(yuǎn)等不到發(fā)送結(jié)束的標(biāo)志。
3.還有人在中斷程序中,并沒(méi)有區(qū)分中斷的來(lái)源,反而讓發(fā)送引起的中斷,執(zhí)行了接收中斷的程序。
對(duì)此,做而論道發(fā)表自己常用的方法:
接收數(shù)據(jù)時(shí),使用“中斷方式”,清除 RI 后,用一個(gè)變量通知主函數(shù),收到新數(shù)據(jù)。
發(fā)送數(shù)據(jù)時(shí),也用“中斷方式”,清除 TI 后,用另一個(gè)變量通知主函數(shù),數(shù)據(jù)發(fā)送完畢。
這樣一來(lái),收、發(fā)兩者基本一致,編寫(xiě)程序也很規(guī)范、易懂。
更重要的是,主函數(shù)中,不用在那兒死等發(fā)送完畢,可以有更多的時(shí)間查看其它的標(biāo)志。


實(shí)例:
求一個(gè)PC與單片機(jī)串口通信的程序,要求如下:
1、如果在電腦上發(fā)送以$開(kāi)始的字符串,則將整個(gè)字符串原樣返回(字符串長(zhǎng)度不是固定的)。
2、如果接收到1,則將P10置高電平,接收到0,P10置低電平。(用來(lái)控制一個(gè)LED
單片機(jī)是STC89C52RC/晶振11.0592/波特率要求是9600或4800。謝謝!
問(wèn)題補(bǔ)充:可能會(huì)將【$ABCD,123456,987654ccc,aasdasd,aaaa,sssd,4D】這樣的字符串(字符串長(zhǎng)度約為50-150個(gè)字符)傳送給單片機(jī),只能能原樣返回。

最佳答案:
下列程序,已經(jīng)調(diào)試成功。
#include
sbit LED = P1^0;
unsigned char UART_buff;
bit New_rec = 0, Send_ed = 1, Money = 0;
//----------------------------------------------
void main (void)
{
SCON = 0x50; //串口方式1, 8-n-1, 允許接收.
TMOD = 0x20; //T1方式2
TH1 = 0xFD; [url=]//9600bps@11.0592MHz[/url]
TL1 = 0xFD;
TR1 = 1;
ES= 1; //開(kāi)中斷.
EA= 1;
while(Money == 0); //等著交費(fèi),呵呵,等著接收$.
while(1){
if ((New_rec == 1) && (Send_ed == 1)){//如果收到新數(shù)據(jù)及發(fā)送完畢
SBUF = UART_buff; //那就發(fā)送.
New_rec = 0;
Send_ed = 0;
} }
}
//----------------------------------------------
void ser_int (void) interrupt 4
{
if(RI == 1) {//如果收到.
RI = 0; //清除標(biāo)志.
New_rec = 1;
UART_buff = SBUF;//接收.
if(UART_buff == 1)LED = 1;
if(UART_buff == 0)LED = 0;
if(UART_buff == $)Money = 1;
}
else{ //如果送畢.
TI = 0; //清除標(biāo)志.
Send_ed = 1;
}
}
//----------------------------------------------


關(guān)鍵詞: 51單片機(jī)串口問(wèn)

評(píng)論


技術(shù)專區(qū)

關(guān)閉