51單片機(jī)之寄存器-3.3單片機(jī)串口通信之發(fā)送與接收
由于現(xiàn)在很多筆記本已經(jīng)沒有串口,我們通常采用USB轉(zhuǎn)串口。先來看圖1中的一個例子,現(xiàn)在想讓P1把在A地點的D3,D5,D8,D9,D11組球通過P2的幫忙一個一個傳遞到B點,要求按順序傳遞,而且傳遞完成后不能打亂順序。如果不做任何處理,只要P1在某一組中如D3組,有一個球傳錯或者漏傳,那么將導(dǎo)致后面的傳遞全部錯位。改進(jìn)的方法就是在傳每組第一個球時,先傳個紅色的標(biāo)簽,告訴P2接下來要傳的是這一組的第一個球。當(dāng)這一組傳遞完成后,再給一個綠色的標(biāo)簽,告訴P2,這一組的球傳遞完畢。這樣即使某一組傳錯了,也不會影響下一組的傳遞?,F(xiàn)在我們詳細(xì)看看這個過程。(1) P1需要選擇傳哪一組的球。(2) 準(zhǔn)備好標(biāo)記 (3) 通知P2現(xiàn)在要開始工作. 同時在傳遞過程要保證P1和P2的速度一致,否則傳遞也會出問題。知道了這個例子,現(xiàn)在我們詳細(xì)的來討論一下串口異步通信。
本文引用地址:http://m.butianyuan.cn/article/201611/319548.htm如圖所示,兩個單片機(jī)的串行通信,傳送一根線TXD,接收一根線RXD,現(xiàn)在我們只討論傳送這部分。設(shè)定單片機(jī)1為我們開發(fā)板上的型號STC89C52RC. 既然是傳送,那么傳送什么內(nèi)容。現(xiàn)在假設(shè)我要傳送0111000B(38H)這個數(shù)據(jù)。那么怎么讓單片機(jī)知道我要傳這個數(shù)據(jù)呢?如上圖所示,只需要使用圖中SBUF=dataTXD(即SBUF=0x38)這個語句。當(dāng)單片機(jī)看到這條指令后,把0x38寫入SBUF,就啟動串行通信的發(fā)送。也就是說,這條語句告訴了單片機(jī)兩個信息,1.發(fā)送什么內(nèi)容,2.現(xiàn)在就開始發(fā)送。單片機(jī)就開始以0和1的方式開始發(fā)送了。那么這樣又出現(xiàn)問題了,單片機(jī)2怎么知道單片機(jī)1要給我傳數(shù)據(jù)了?最簡單的方法的就是給需要傳送的數(shù)據(jù)前后加個標(biāo)簽,這樣兩個標(biāo)簽之間的內(nèi)容就是單片機(jī)1要傳送的信息了。當(dāng)然也可以在8位數(shù)據(jù)后添加其他標(biāo)簽,這個就是串口的傳送方式了。這個由SCON串行控制器來設(shè)置:
這里我們選擇工作方式1,SM0/SM1設(shè)置為0/1。8位數(shù)據(jù)位加起始位和停止位,一共10位,也稱為一幀。那么這個起始位和停止位什么加入呢?當(dāng)單片機(jī)TXD發(fā)送信息時,單片機(jī)就自動加入了。因此,這里我們總結(jié)一下,SBUF=dataTXD當(dāng)執(zhí)行到這條指令時,告訴了單片機(jī)三個重要信息,1. 要傳送什么信息,2. 什么時候開始傳, 3. 自動在這個數(shù)據(jù)前添加開始位和停止位。但是又有個問題,傳多快呢?這里需要引入一個概念,波特率。波特率定義為每秒傳輸?shù)拇a元個數(shù),單位是波特(Baud),簡寫為B。而每秒鐘傳送的二進(jìn)制數(shù)碼的位數(shù)則定義為比特率,單位是比特每秒,b/s或bps。在串行通信系統(tǒng)中,傳送的信號可能是二進(jìn)制,八進(jìn)制,十進(jìn)制等,只有在二進(jìn)制通信系統(tǒng)中波特率和比特率在數(shù)值上才是相等。本教程所描述的串行通信傳輸信號都是采用二進(jìn)制信號傳送的,故比特率和波特率相等。例如,通信雙方每秒所傳送的信息量是480字節(jié),每一字節(jié)包含10位(1個起始位,8個數(shù)據(jù)位,1個停止位),則波特率為:
480×10=4800b/s=4800B
這里需要注意相互通信的甲乙雙方必須具有相同的波特率,否則無法成功完成串行數(shù)據(jù)通信。如上圖所示,給出了串行通信工作方式1的波特率。
現(xiàn)在來總結(jié)一下,串口通信的發(fā)送步驟
(1)選擇工作方式
(2)設(shè)置速度
(3)發(fā)送什么信息,打上標(biāo)記,開始傳送
以上3個步驟中,第三步中三個任務(wù)通過SBUF=0x38(假設(shè)我要傳這個數(shù)據(jù))這句代碼就全部完成了。因此在此之前我們要先設(shè)置好工作方式和傳送速度(波特率).
這些步驟不需要記憶,只需要打開串口助手就一目了然了,
參考代碼如下:
#include "reg52.h"
void delayUs(unsigned char t);
void delayMs(unsigned char t);
void main(void)
{
SM0=0;
SM1=1;//串口工作模式
TMOD=0X20;
TH1=TL1=253; //波特率9600
TR1=1;
while(1)
{
SBUF=0x38;
delayMs(250);
delayMs(250);
}
}
void delayUs(unsigned char t)
{
while(--t);
}
void delayMs(unsigned char t)
{
while(--t)
{
delayUs(245);
delayUs(245);
}
}
既然知道如何操作串口通信如何發(fā)送,我們按照同樣的思路看看如何操作串口接收。首先接收到的信息在哪里?將SBUF=dataTXD替換為dataRXD=SBUF. 前者表示把數(shù)據(jù)寫進(jìn)SBUF,發(fā)送;后者表示把SBUF中的數(shù)據(jù)讀出了,接收。注意接收緩沖器SBUF和發(fā)送緩沖器SBUF名字一樣,地址也一樣,但是是兩個獨立的物理空間。工作方式的選擇與速度設(shè)置與前面一樣。那么,怎么讓單片機(jī)知道開始接收呢?需要滿足兩個條件,TI=0和REN=1. REN表示串口接收允許。另外,當(dāng)接收完成一幀數(shù)據(jù)(8位)后,控制信號復(fù)位,中斷標(biāo)志RI被置"1",呈中斷申請狀態(tài)。在工作方式1下,同時滿足SM2=0,RI=0接收數(shù)據(jù)有效。我們可以整理一下串口接收的過程如下,
(1)選擇工作方式(工作方式1)
(2)設(shè)置速度
(3)開始接收(TI=0,REN=1)
(4)接收的信息在哪里。(dataRXD=SBUF)
(5)接收的數(shù)據(jù)有效(SM2=0,RI=0)
串行通信接收的參考代碼如下:
#include "reg52.h"
#define uchar unsigned char
void delayUs(unsigned char t);
void delayMs(unsigned char t);
void main(void)
{
uchar MyRevData;
SM0=0;
SM1=1;//串口工作模式1
REN=1;
TMOD=0X20;
TH1=TL1=253; //波特率9600
TR1=1;
while(1)
{
MyRevData=SBUF;
delayMs(250);
P1=MyRevData;
delayMs(250);
RI=0; //當(dāng)接收完成一幀數(shù)據(jù)(8位)后,控制信號復(fù)位,中斷標(biāo)志RI被置"1",呈中斷申請狀態(tài)。在工作方式1下,SM2=0,RI=0數(shù)據(jù)有效
}
}
void delayUs(unsigned char t)
{
while(--t);
}
void delayMs(unsigned char t)
{
while(--t)
{
delayUs(245);
delayUs(245);
}
}
將代碼編譯燒寫后進(jìn)行測試,打開STC-ISP燒寫軟件,選中串口助手,設(shè)置COM端口,波特率等參數(shù),打開串口,然后輸入要傳送的內(nèi)容,如下圖所示。
在發(fā)送區(qū)內(nèi)輸入FF后點擊"發(fā)送字符/數(shù)據(jù)",LED全部熄滅,輸入00,點擊發(fā)送,LED全部點亮
評論