1. 程式人生 > >深入理解51微控制器串列埠通訊

深入理解51微控制器串列埠通訊

串列埠通訊的基本認識

通訊分為並行通訊和序列通訊,並行通訊時的資料各個位同時傳送,可以實現位元組為單位通訊,但通訊線多佔用資源,成本高。以前用到的的P1=0x55,一次給P1口的8個管腳分別賦值,同時進行訊號輸出,類似於8個車道可以過去8輛車,這樣的形式是並行的,一般稱P0,P1,P2,P3為51微控制器的4組並行匯流排。
序列通訊,就是一個車道,一個只能通過一輛車,如果一個0x55這樣一個位元組的資料要傳輸過去的話,假如低位在前,高位在後的話,那傳送方式是:0-1-0-1-0-1-0-1,一位一位的進行傳輸,要傳送8次才能傳送完一個位元組
STC89C52有兩個引腳是專門用來做串列埠通訊的,一個是P3.0(RXD),一個是P3.1(TXD),他們組成的通訊介面就是序列介面,簡稱串列埠。用於兩個微控制器進行UART通訊。兩微控制器通訊介面連線方式:RXD——TXD,TXD——RXD。
微控制器1的TXD傳送通道接到微控制器2的RXD接收通道,微控制器的1的RXD接收通道接到微控制器2的TXD傳送通道,從而實現相互通訊。
當微控制器1想給微控制器2傳送資料,比如傳送了0xCE,用二進位制表示就是11001110,在串列埠通訊過程中,是低位先發,高位後發的原則,那麼就是讓TXD首先拉低電平,持續一段時間,傳送一位0,然後拉高電平,持續一段時間,傳送一位1,繼續拉高,在持續一段時間,傳送一位1,一直把8位二進位制數11001110全部發送完畢,這裡涉及到一個問題,就是持續的一個時間段時間“到底是多少”。因而便引入通訊中非常重要的一個概念波特率,也叫做位元率。

波特率

波特率就是傳送二進位制資料位的速率,習慣用baud表示,即我們傳送一位二進位制資料持續的時間=1/baud。在通訊之前,微控制器1和微控制器2首先都要明確約定好他們之間的通訊波特率,必須保持一致,收發雙方才能正常通訊。 
約定好速度之後,我們還要考慮第二個問題,資料什麼時候是起始,什麼時候是結束?提前和延遲結束都會接收錯誤。在uart通訊的時候,一個位元組是8位,規定當沒有通訊訊號發生時,通訊線路保持高電平,當資料傳送前,先發一位0表示起始位,然後傳送8位資料位,資料位是先低再高,數位位傳送完後才呢個後再發送一位1表示停止位,這樣我們要傳送的8位資料,實際上我們傳送了10位,多出來兩位其中一個是起始位,一個是停止位。而接受方一直保持的高電平,一旦檢測到一位低電平,準備開始接受資料,接受8位資料後,然後檢測停止位,再準備下一個數據接收。 串列埠資料傳送示意圖,實際上是一個時域示意圖,就是訊號隨著時間變化的對應關係。比如在微控制器的傳送引腳上,左邊的是先發生的,右邊的是後發生的,資料位的切換時間就是波特率分之一秒,如果能夠理解時域的概念,後邊很多通訊的時序圖就很容易理解了。

RS232

在我們電腦上,一般都會有一個9針的序列介面,這個序列介面叫做RS232介面,它和UART通訊有關聯,但是由於現在膝上型電腦不帶9針串列埠,所以和微控制器通訊越來越趨於使用USB虛擬串列埠。 
九針串列埠分工頭和母頭 
公頭上5下4,上5從左到右為1.2.3.4.5;下4從左到右為6.7.8.9; 
母頭上5下4,上5從左到右為5.4.3.2.1;下4從左到右為9.8.7.6; 
RS232介面一共有9個引腳,分別定義是:1、載波檢測DCD;2、接收資料RXD;3、傳送資料TXD;4、資料終端準備好DTR;5、訊號地線SG;6、資料準備好DSR;7、請求傳送RTS;8、清除傳送CTS;9、振鈴提示RI。我們要讓這個串列埠和我們微控制器進行通訊,我們只需要關心其中的2腳RXD、3腳TXD和5腳GND即可 
雖然這三個引腳的名字和我們微控制器上的串列埠名字一樣,但是卻不能直接和微控制器對連通訊,這是為什麼呢?隨著我們瞭解的內容越來越多,我們得慢慢知道,不是所有的電路都是5V代表高電平而0V代表低電平的。對於RS232標準來說,它是個反邏輯,也叫做負邏輯。為何叫負邏輯?它的TXD和RXD的電壓,-3V~-15V電壓代表是1,+3~+15V電壓代表是0。低電平代表的是1,而高電平代表的是0,所以稱之為負邏輯。因此電腦的9針RS232串列埠是不能和微控制器直接連線的,需要用一個電平轉換晶片MAX232來完成 
這個晶片就可以實現把標準RS232串列埠電平轉換成我們微控制器能夠識別和承受的UART 0V/5V電平。從這裡大家似乎慢慢有點明白了,其實RS232串列埠和UART串列埠,它們的協議型別是一樣的,只是電平標準不同而已,而MAX232這個晶片起到的就是中間人的作用,它把UART電平轉換成RS232電平,也把RS232電平轉換成UART電平,從而實現標準RS232介面和微控制器UART之間的通訊連線。

USB轉串列埠通訊

隨著技術的發展,工業上還有RS232串列埠通訊的大量使用,但是商業技術的應用上,已經慢慢的使用USB轉UART技術取代了RS232串列埠,絕大多數膝上型電腦已經沒有串列埠這個東西了,那我們要實現微控制器和電腦之間的通訊該怎麼辦呢? 
們只需要在電路上新增一個USB轉串列埠晶片,就可以成功實現USB通訊協議和標準UART序列通訊協議的轉換,在我們的開發板上,我們使用的是CH340T這個晶片 
我們需要用跳線帽把中間和下邊的針短接在一起。右側的CH340T這個電路很簡單,把電源、晶振接好後,6腳和7腳的DP和DM分別接USB口的2個數據引腳上去,3腳和4腳通過跳線接到了我們微控制器的TXD和RXD上去。 
CH340T的電路里3腳位置加了個4148的二極體,是一個小技巧。因為STC89C52這個微控制器下載程式時需要冷啟動,就是先點下載後上電,上電瞬間微控制器會先檢測需要不需要下載程式。雖然微控制器的VCC是由開關來控制,但是由於CH340T的3腳是輸出引腳,如果沒有此二極體,開關後級微控制器在斷電的情況下,CH340T的3腳和微控制器的P3.0(即RXD)引腳連在一起,有電流會通過這個引腳流入後級電路並且給後級的電容充電,造成後級有一定幅度的電壓,這個電壓值雖然只有兩三伏左右,但是可能會影響到正常的冷啟動。加了二極體後,一方面不影響通訊,另外一個方面還可以消除這種不良影響。這個地方可以暫時作為了解,大家如果自己做這類電路,可以參考一下。

IO口模擬UART串列埠通訊

UART串列埠波特率,常用的值是300、600、1200、2400、4800、9600、14400、19200、28800、38400、57600、115200等速率。IO口模擬UART序列通訊程式是一個簡單的演示程式,我們使用串列埠除錯助手下發一個數據,資料加1後,再自動返回。 
串列埠除錯助手,這裡我們直接使用STC-ISP軟體自帶的串列埠除錯助手,先把串列埠除錯助手的使用給大家說一下,如圖11-6所示。第一步要選擇串列埠助手選單,第二步選擇十六進位制顯示,第三步選擇十六進位制傳送,第四步選擇COM口,這個COM口要和自己電腦裝置管理器裡的那個COM口一致,波特率按我們程式設定好的選擇,我們程式中讓一個數據位持續時間是1/9600秒,那這個地方選擇波特率就是選9600,校驗位選N,資料位8,停止位1。 
串列埠除錯助手的實質就是利用電腦上的UART通訊介面,傳送資料給我們的微控制器,也可以把我們的單片機發送的資料接收到這個除錯助手介面上。 
因為初次接觸通訊方面的技術,所以我把後面的IO模擬串列埠通訊程式進行一下解釋,大家可以邊看我的解釋邊看程式,把底層原理先徹底弄懂。

變數定義部分就不用說了,直接看main主函式。首先是對通訊的波特率的設定,在這裡我們配置的波特率是9600,那麼串列埠除錯助手也得是9600。配置波特率的時候,我們用的是定時器T0的模式2。模式2中,不再是TH0代表高8位,TL0代表低8位了,而只有TL0在進行計數,當TL0溢位後,不僅僅會讓TF0變1,而且還會將TH0中的內容重新自動裝到TL0中。這樣有一個好處,就是我們可以把想要的定時器初值提前存在TH0中,當TL0溢位後,TH0自動把初值就重新送入TL0了,全自動的,不需要程式中再給TL0重新賦值了,配置方式很簡單,大家可以自己看下程式並且計算一下初值。 
波特率設定好以後,開啟中斷,然後等待接收串列埠除錯助手下發的資料。接收資料的時候,首先要進行低電平檢測while (PIN_RXD),若沒有低電平則說明沒有資料,一旦檢測到低電平,就進入啟動接收函式StartRXD()。接收函式最開始啟動半個波特率週期,初學可能這裡不是很明白。大家回頭看一下我們的圖11-2裡邊的串列埠資料示意圖,如果在資料位電平變化的時候去讀取,因為時序上的誤差以及訊號穩定性的問題很容易讀錯資料,所以我們希望在訊號最穩定的時候去讀資料。除了訊號變化的那個沿的位置外,其它位置都很穩定,那麼我們現在就約定在訊號中間位置去讀取電平狀態,這樣能夠保證我們讀的一定是正確的。 
一旦讀到了起始訊號,我們就把當前狀態設定成接收狀態,並且開啟定時器中斷,第一次是半個週期進入中斷後,對起始位進行二次判斷一下,確認一下起始位是低電平,而不是一個干擾訊號。以後每經過1/9600秒進入一次中斷,並且把這個引腳的狀態讀到RxdBuf裡邊。等待接收完畢之後,我們再把這個RxdBuf加1,再通過TXD引腳傳送出去,同樣需要先發一位起始位,然後發8個數據位,再發結束位,傳送完畢後,程式執行到while (PIN_RXD),等待第二輪訊號接收的開始。

串列埠通訊基本應用

通訊的三種基本型別

常見的通訊傳輸方式可以分為單工通訊、半雙工通訊、全雙工通訊。 
單工通訊就是隻允許一個方向向另外一個方向傳送資訊,而另外一方不能回傳訊息。比如:電視遙控器、收音基等 
半雙工通訊是指資料可以在雙方之間相互傳播,但是同一時刻只能呢個其中一方發給另一方,比如:對講機 
全雙工通訊是指傳送資料同時也能接收資料,兩者同步進行,就如同我們的電話一樣,我們說的同時也可以聽到對方的聲音。

uart模組介紹

IO口模擬串列埠通訊,讓大家瞭解了串列埠通訊的本質,但是我們的微控制器程式卻需要不停的檢測掃描微控制器IO口收到的資料,大量佔用了微控制器的執行時間。這時候就會有聰明人想了,其實我們並不是很關心通訊的過程,我們只需要一個通訊的結果,最終得到接收到的資料就行了。這樣我們可以在微控制器內部做一個硬體模組,讓它自動接收資料,接收完了,通知我們一下就可以了,我們的51微控制器內部就存在這樣一個UART模組,要正確使用它,當然還得先把對應的特殊功能暫存器配置好。 
51微控制器的UART串列埠的結構由序列口控制暫存器SCON、傳送和接收電路三部分構成,先來了解一下串列埠控制暫存器SCON。 
SCON序列控制器的位分配(地址:0x98) 
位:符號:復位值: 0:RI:0;1:TI:0;2:RB8:0;3:TB8:0;4:REN:0;5:SM2:0;6:SM1:0;7:SM0:0; 
0位RI:接收中斷標誌位,當接收電路接收到停止位的中間位置時,RI由硬體置1,必須通過軟體清零 
1位TI:傳送中斷標誌位,當傳送電路傳送到停止位的中間位置時,TI由硬體置1,必須通過軟體清零。 
2位RB8:模式2和3中接收到的第9位資料(很少用),模式1用來接收停止位。 
3位TB8:模式2和3中要傳送的第9位資料(很少用)。 
4位REN:使能序列接收。由軟體置位使能接收,軟體清零則禁止接收。 
5位SM2:多機通訊控制位(極少用),模式1直接清零。 
6位SM1和7位SM0: 
這兩位共同決定了串列埠通訊的模式0~模式3共4種模式。我們最常用的就是模式1,也就是SM0=0,SM1=1,下邊我們重點就講模式1,其它模式從略。 
對於串列埠的四種模式,模式1是最常用的,就是我們前邊提到的1位起始位,8位資料位和1位停止位。下面我們就詳細介紹模式1的工作細節和使用方法,至於其它3種模式與此也是大同小異,真正遇到需要使用的時候大家再去查閱相關資料就行了。 
在我們使用IO口模擬串列埠通訊的時候,串列埠的波特率是使用定時器T0的中斷體現出來的。在硬體串列埠模組中,有一個專門的波特率發生器用來控制傳送和接收資料的速度。對於STC89C52微控制器來講,這個波特率發生器只能由定時器T1或定時器T2產生,而不能由定時器T0產生,這和我們模擬的通訊是完全不同的概念。 
如果用定時器2,需要配置額外的暫存器,預設是使用定時器1的,我們本章內容主要就使用定時器T1作為波特率發生器來講解,方式1下的波特率發生器必須使用定時器T1的模式2,也就是自動重灌載模式,定時器的過載值計算公式為: 
TH1 = TL1 = 256 - 晶振值/12 /2/16 /波特率

和波特率有關的還有一個暫存器,是一個電源管理暫存器PCON,他的最高位可以把波特率提高一倍,也就是如果寫PCON |= 0x80以後,計算公式就成了: 
TH1 = TL1 = 256 - 晶振值/12 /16 /波特率 
公式中數字的含義這裡解釋一下,256是8位定時器的溢位值,也就是TL1的溢位值,晶振值在我們的開發板上就是11059200,12是說1個機器週期等於12個時鐘週期,值得關注的是這個16,我們來重點說明。在IO口模擬串列埠通訊接收資料的時候,採集的是這一位資料的中間位置,而實際上串列埠模組比我們模擬的要複雜和精確一些。他採取的方式是把一位訊號採集16次,其中第7、8、9次取出來,這三次中其中兩次如果是高電平,那麼就認定這一位資料是1,如果兩次是低電平,那麼就認定這一位是0,這樣一旦受到意外干擾讀錯一次資料,也依然可以保證最終資料的正確性。 
串列埠通訊的傳送和接收電路在物理上有2個名字相同的SBUF暫存器,它們的地址也都是0x99,但是一個用來做傳送緩衝,一個用來做接收緩衝。意思就是說,有2個房間,兩個房間的門牌號是一樣的,其中一個只出人不進人,另外一個只進人不出人,這樣的話,我們就可以實現UART的全雙工通訊,相互之間不會產生干擾。但是在邏輯上呢,我們每次只操作SBUF,微控制器會自動根據對它執行的是“讀”還是“寫”操作來選擇是接收SBUF還是傳送SBUF,後邊通過程式,我們就會徹底瞭解這個問題。 
##UART串列埠程式 
一般情況下,我們編寫串列埠通訊程式的基本步驟如下所示: 
1、配置串列埠為模式1。 
2、配置定時器T1為模式2,即自動重灌模式。 
3、根據波特率計算TH1和TL1的初值,如果有需要可以使用PCON進行波特率加倍。 
4、開啟定時器控制暫存器TR1,讓定時器跑起來。 
這裡還要特別注意一下,就是在使用T1做波特率發生器的時候,千萬不要再使能T1的中斷了。 
我們先來看一下由IO口模擬串列埠通訊直接改為使用硬體UART模組時的程式程式碼,看看程式是不是簡單了很多,因為大部分的工作硬體模組都替我們做了。程式功能和IO口模擬的是完全一樣的。

通訊例項與ASCLL碼

先拋開我們使用的漢字不談,那麼我們常用的字元就包含了0~9的數字、A~Z/a~z的字母、還有各種標點符號等。那麼在微控制器系統裡面我們怎麼來表示它們呢?ASCII碼(American Standard Code for Information Interchange,即美國資訊互換標準程式碼)可以完成這個使命:我們知道,在微控制器中一個位元組的資料可以有0~255共256個值,我們取其中的0~127共128個值賦予了它另外一層涵義 
我們用字元格式傳送一個小寫的a,返回一個十六進位制的0x61,數碼管上顯示的也是61,ASCII碼錶裡字元a對應十進位制是97,等於十六進位制的0x61;我們再用字元格式傳送一個數字1,返回一個十六進位制的0x31,數碼管上顯示的也是31,ASCII表裡字元1對應的十進位制是49,等於十六進位制的0x31。這下大家就該清楚了:所謂的十六進位制傳送和十六進位制接收,都是按位元組資料的真實值進行的;而字元格式傳送和字元格式接收,是按ASCII碼錶中字元形式進行的,但它實際上最終傳輸的還是一個位元組資料。這個表格,當然不需要大家去記住,理解它,用的時候過來查就行了。