天天看點

串行口通信(一)

串行口通信(一)

前言

人類生存于世,少不了溝通。溝通使人類互相認知,傳遞資訊,提升生活品質。但然單片機也需要,不然單單一個機器,無法構成一個系統,發揮更大的力量。隻有單片機與外圍裝置傳遞資訊,互相回報才會有一個完美的系統。串行口通信就被發明出來,下面來了解串行口通信(uart)。

幾個概念

為了能更好了解串行口通信,在介紹它之前,先來看看幾個概念,補充知識,友善深入明白uart工作原理。

通信方式

通信方式

通信方式有兩種,分别是并行通信和串行通信。

并行通信:并行是指多比特資料同時通過并行線進行傳送,這樣資料傳送速度大大提高,但并行傳送的線路長度受到限制,因為長度增加,幹擾就會增加,資料也就容易出錯。

串行通信:串行通信是指 使用一條資料線,将資料一位一位地依次傳輸,每一位資料占據一個固定的時間長度。其隻需要少數幾條線就可以在系統間交換資訊,特别适用于計算機與計算機、計算機與外設之間的遠距離通信。

拿汽車通道來說,并行通信就是多車道,多輛車一起行駛,而串行通信就是單車道,隻能一輛一輛車通過。

串行通信制式

串行通信制式

串行通信制式有單工通信,半雙工通信,雙工通信三種。

單工通信:單工通信信道是單向信道,發送端和接收端的身份是固定的,發送端隻能發送資訊,不能接收資訊;接收端隻能接收資訊,不能發送資訊,資料信号僅從一端傳送到另一端,即資訊流是單方向的。

半雙工通信:半雙工資料傳輸指資料可以在一個信号載體的兩個方向上傳輸,但是不能同時傳輸。例如,在一個區域網路上使用具有半雙工傳輸的技術,一個工作站可以線上上發送資料,然後立即線上上接收資料,這些資料來自資料剛剛傳輸的方向。像全雙工傳輸一樣,半雙工包含一個雙向線路(線路可以在兩個方向上傳遞資料)。

雙工通信:雙工通信是指在同一時刻資訊可以進行雙向傳輸,和打電話一樣,說的同時也能聽,邊說邊聽。這種發射機和接收機分别在兩個不同的頻率上(兩個頻率差有一定要求)能同時進行工作的雙工機也稱為異頻雙工機。

三種通信制式很容易了解,對照上圖看,單工通信不就是單方面通信,隻能發出指令或接收指令。半雙工通信就是能接收又能發送,但是不能同時進行。雙工就最厲害,可以同時發送和接收指令。

串行通信分類

串行通信有兩種,一位異步串行通信,二為同步串行通信。

異步串行通信:異步串行通信是指通信雙方以一個字元(包括特定附加位)作為資料傳輸機關且發送方傳送字元的間隔時間不一定,具有不規則資料段傳送特性的串行資料傳輸。

同步串行通信:所謂同步通信是指在約定的通信速率下,發送端和接收端的時鐘信号頻率和相位始終保持一緻(同步),這就保證了通信雙方在發送和接收資料時具有完全一緻的定時關系。

兩種串行通信不同就隻有時間,在發送字元時,異步可以是不同時間間隔發送,但同步隻能以固定的時間間隔發送。

波特率

波特率:波特率表示每秒鐘傳送的二進制位數,是衡量資料傳送速率的名額,它用機關時間内載波調制狀态改變的次數來表示。

互相通信的甲乙雙方必須具有相同的波特率,不然無法成功完成串行通信。

概述

52單片機具有一個全雙工串行通信口。一個全雙工UART(通用異步接收發送器)的串行I/O口,用于實作單片機之間或單片機與微機之間的串行通信;片内振蕩器和時鐘産生電路,石英晶體和微調電容需要外接。最佳振蕩頻率為6M—12M。管腳RXD( P3.0),TXD(P3.1)與序列槽通信有關。波特率可以設定。

内部結構

串行口内部結構邏輯圖

串行口通信與三個寄存器有關,分别是:

 1. PCON寄存器
 2. SCON寄存器
 3. SBUF特殊功能寄存器
           

寄存器

PCON電源管理寄存器

串行口通信(一)

電源管理寄存器

SMOD:該位與序列槽通信有關。

SMOD=0; 序列槽方式1,2,3時,波特率正常。

SMOD=1; 序列槽方式1,2,3時,波特率加倍。

LVDF:低電壓檢測标志位,同時也是低電壓檢測中斷請求标志位

GF1,GF0:兩個通用工作标志位,使用者可以***使用。

PD:掉電模式設定位。

PD=0 單片機處于正常工作狀态。

PD=1 單片機進入掉電(Power Down)模式 ,可由外部中斷或硬體複位模式喚醒,進入掉電模式後,外部晶振停振,CPU、定時器、串行口全部停止工作,隻有外部中斷工作。在該模式下,隻有硬體複位和上電能夠喚醒單片機。

IDL:空閑模式設定位。

IDL=0 單片機處于正常工作狀态。

IDL=1 單片機進入空閑(Idle)模式,除CPU不工作外,其餘仍繼續工作,在空閑模式下可由任一個中斷或硬體複位喚醒。

這個寄存器隻有SMOD位與串行口通信有關。系統複位預設為SMOD=0。當為用52單片機的定時器2産生波特率時,波特率不受SMOD影響。用定時器1産生波特率時,不去設定,就預設為0,波特率正常,設定為1時,波特率加倍。

SCON串行口控制寄存器

串行口通信(一)

串行口控制寄存器

SM0,SM1:共同決定串行口工作模式。

SM2:多機通信控制位。在方式0中,SM2一定要等于0。在方式1中,當SM2為1時則隻有接收到有效停止位時,RI才置1。在方式2或3中,當SM2為1且接收到的第9位資料RB8為0時,RI才置1。

REN:接收允許控制位。由 軟體置位以允許接收,又由 軟體清零來禁止接收。

TB8:要發送資料的第9位。在方式2或3中,要發送的第9位資料,根據需要由軟體置1或清零軟體置1或清零。例如,可約定作為奇偶校驗位,或在多機通信中作為差別位址幀或資料幀的标志位。(很少用)

RB8:接收到的資料的第9位。在方式0中不使用RB8。在方式1中,若SM2為0,RB8為接收到的停止位。在方式2或3中,RB8為到的第9位資料。(很少用)

TI:發送中斷标志。在方式0中,第8位發送結束時,由 硬體置位。在其它方式的發送停止位前,由 硬體置位。TI置位既表示一幀資訊發送結束,同時也向CPU申請中斷。可根據需要,用軟體查詢的方法獲得資料已發送完畢的資訊,或用中斷的方式來發送下一個資料。TI必須用 軟體清零。

RI:接收中斷标志位。在方式0中,當接收完第8位資料後,由 硬體置位。在其它方式中,在接收到停止位的中間時刻由硬體置位(例外情況見對SM2的說明)。RI表示一幀資料接收完畢,可用查詢的方法獲知或者用中斷的方法獲知。RI也必須用 軟體清零。

串行口通信(一)

串行口工作模式

由于52單片機内部有一個硬體子產品,讓它自動接收資料,接收完了,通知我們一下就可以了,就不需要再手動配置TB8,RB8。隻要配置好SCON,内部就自動幫弄好了。

SBUF特殊功能寄存器

特殊功能寄存器

SBUF是指串行口中的兩個緩沖寄存器,一個是發送寄存器,一個是接收寄存器,在實體結構上是完全獨立的,但位址是重疊的。它們都是位元組尋址的寄存器,位元組位址均為99H。隻要在編寫程式時,用不同指令即可操作兩個寄存器。

比如,SBUF=A;這個是指将A的資料移入發送寄存器,然後發送寄存器再把資料發送出去。A=SBUF;則是指将接受寄存器中的資料指派給A。

串行口方式1

方式1邏輯圖

串行口為10位通用異步接口。發送或接收一幀資料資訊為10位,包括1位起始位“0”、8位資料位、1位停止位“1”。發送資料:資料從TXD端口輸出,當資料寫入發送緩沖器SBUF時,就啟動發送器發送。發送完一幀資料後,置中斷标志TI=1,申請中斷,通知CPU可以發送下一個資料了。接收資料:首先使REN=1(允許接收資料),串行口從RXD接收資料,當采樣到1至0跳變時,确認是起始位“0”,就開始接收一幀資料,當接收完一幀資料時,置中斷标志RI=1,申請中斷,通知CPU從SBUF取走接收到的資料 。

計算波特率

方式1波特率計算

溢出速率即溢出頻率,隻要算出定時器每溢出一次所需要的時間T,那溢出率就是1/T。計算在沒有波特率加倍(SMOD=0)的情況下,波特率為9600bps時怎樣指派計數器。這裡說明一下,由于波特率是需要很精确的,不然通信會出錯。如果采用定時器工作模式1,采用人工重載,會有較大誤差,因為進入中斷函數也需要時間,累積時間就會出錯。是以這裡運用工作模式2,8位自動重裝。計數器自動重裝不需人工幹預,減少誤差。

對照上面公式,波特率不加倍,SMOD=0,工作模式2,那n=8,波特率=9600,就可以算出x=253,十六進制為fd。

編寫步驟

  1. 設定串行口方式
  2. 設定定時器工作模式
  3. 計數器寄存器指派
  4. 中斷寄存器控制
  5. 啟動定時器中斷
  6. 發送函數
  7. 接收函數

範例1

#include<reg52.h>
unsigned char date;    //定義變量資料中斷
bit flag;  //定義變量标志
void send (); //聲明發送函數
void receive (); //聲明接收函數
void initialize ();    //聲明初始化函數
main()
{        
    initialize();  //調用初始化函數
    while(1)
    {
        send();    //調用發送函數
        receive(); //調用接收函數
    }
}
void initialize()  //初始化函數
{
    SCON=0X50;     //0011 0000 串行口工作模式1
    TMOD = 0X20;    //定時器1工作模式2,8為自動重裝
    TH1 = 0xFD;     //設定定時初值        波特率為9600
    TL1 = 0xFD;     //設定定時器重裝值
    TR1 = 1;        //啟動定時器1
    IE=0;
}
void send()         //發送函數
{
    if(flag==1)    //證明已經接收資料
    {   
        SBUF=date;    //将接收的資料發送出去
        while(!TI);   //等待發送中斷
        TI=0;         //軟體置0
        flag=0;       //清零
    }

}
void receive()       //接收函數
{
    while(!RI);   //等待接收中斷
    date=SBUF;    //将收到的資料存進接收緩沖寄存器
    RI=0;        //軟體置0
    flag=1;      //将标志位置1
}
           

範例1是将接受的資料原封不動發送出去。采用查詢法,故不需要打開序列槽中斷,不用中斷函數。隻需不斷查詢TI,RI的值,就知道資料接收發送情況。

範例2

#include<reg52.h>
unsigned char date;
bit flag;
main ()
{
    SCON=0X50;      //初始化
    TMOD=0X20;
    TH1=0XFD;                                   
    TL1=0XFD;
    IE=0X90;
    TR1=1;
    while(1);
}
void interrupt_uart() interrupt 4     //中斷函數
{
    if(RI==1)        //判斷有無資料接收
    {
        date=SBUF;     //将寄存器的值賦給變量
        RI=0;          //置0
        flag=1;        //标志位置1
    }
    if(flag==1)             //已接收資料
    {
        SBUF=date;        //将資料發出
        while(!TI);
        TI=0;
        flag=0;
    }
}
           

與範例1如出一撤,就不詳細注釋。

總結

在序列槽通信中,方式1是最常用的,要認真了解方式1。串行資料一位一位的已經不用處理了,52單片機已經有一個子產品處理完了。隻要知道接收一個資料,産生一次接收中斷,要軟體置0.,發送一個資料會産生一次發送中斷,也要軟體置0。自行置0,處理好資料就OK。下一篇将介紹其他三種方式,歡迎關注。

posted on 2019-02-21 11:11 一個人的朝聖 閱讀(...) 評論(...) 編輯 收藏