1. 程式人生 > >51 微控制器UART 串列埠通訊[ 方式1 ]實現

51 微控制器UART 串列埠通訊[ 方式1 ]實現

1  51序列口結構

51微控制器的UART序列通訊是基於其序列口的可程式設計硬體結構,只要用正確的程式程式碼通過初始化序列口對應暫存器的形式將其序列硬體結構初始化,再編寫符合此序列口通訊的程式程式碼便能夠實現序列通訊,其硬體結構決定了程式設計機制( 當然還要靠51晶片內CPU等機制 )。此結構具有UART( 通用非同步收發器 )的全部功能,能同時進行資料的傳送和接收,也可作為同步移位暫存器使用。此結構集成於微控制器內部。

Figure1:51序列口結構

2  51序列口通訊程式設計機制

決定程式設計機制的先決條件是51微控制器的硬體結構及51晶片內部CPU的執行機制。根據序列通訊口硬體結構,實現UART

通訊可以分為兩步:

(1)初始化序列通訊口( UART )

  •  配置SCON:設定串列埠方式( SM0SM1位配置4種方式 );串列埠是否要接收資料(REN )
  • 設定PCON暫存器的SMOD(若非串列埠方式0 )
  • 若串列埠為方式1和方式3,則需要配置TMOD:選擇定時器1並配置其初值裝載方式(MI M0 ),並設定TH1TL0的初值以確定通訊的波特率(由波特率的計算公式 ),然後配置TCON:開啟定時器1( TR1 )
  • 允許使用中斷( ES ),開啟UART中斷( EA )

(2)程式實現:編寫傳送/接收資料程式碼及中斷服務程式

注:TIRI的置位可檢視SCON暫存器TI  RI被置位的條件

[1]傳送的資料需要通過程式指令“SBUF =資料;”來將資料送往序列傳送緩衝暫存器中,在此條語句後,要用迴圈判斷SCON暫存器中的TI位是否被硬體置位1(表示傳送完畢),等待發送完畢,TI置位被置為1時會進入序列中斷服務程式[由此不能在序列中斷服務程式裡面將TI0,因為從迴圈裡面進入中斷後會返回到迴圈語句中來,所以要在序列中斷服務程式之外將TI0,置0的目的是提供下一次資料傳送成功的依據或進入中斷伺服器程式 ],需要用程式程式碼將TI重新置為0;然後再由CPU控制的時序將資料從TXD( P3.1 )腳發出,經過連線的串列埠線到從裝置(接收資料的裝置 )

[2]獲取接收到資料時需要通過程式指令“存資料變數=SBUF;

”將序列接收緩衝暫存器接收到的資料讀取到程式中來,當接收到資料完畢後,RI會被硬體置位1,此時也會進入序列中斷服務程式,需要用程式指令將RI重新置位0。當然接收資料是由RXD( P3.0 )引腳完成。

[3]序列中斷服務程式的中斷號為4,所以編寫序列中斷服務程式時需要有以下格式:

void 函式名() interrupt 4

{

中斷服務程式內容

}

序列中斷服務函式當TIRI被硬體置位1時才被系統呼叫。TI被硬體置1的情況是,當序列傳送緩衝暫存器內的資料被通過TXD( P3.1 )傳送完畢時( 不同的串列埠方式置1條件不同 )不是指將資料存入序列傳送緩衝器中時TI會被置1,同理RI被置1的情況是當RXD( P3.0 )接收到資料將此資料按位存入序列接收緩衝暫存器內完畢時( 不同串列埠方式置1的條件不同 )不是指從序列接收緩衝暫存器讀完資料時RI會被置1。這個資料的長度和TI( RI )被置位1根據序列通訊方式不同而不同。

對於用程式來實現51微控制器中的序列通訊還需要明確兩點(與其它部分的聯絡):

(1)51微控制器序列通訊的方式1和方式3中,波特率由定時器1的溢位率決定。

(2)SBUF為特殊功能暫存器,它在程式中的兩種不同的指令形式表示不同的含義,當在程式中用寫指令“SBUF=a;”時,表示將a存入序列資料傳送緩衝暫存器中;當在程式中使用讀指令“a=SBUF;”時,表示向序列資料接收緩衝暫存器讀資料並將得到資料賦值於a。接收器具有雙緩衝結構,即在從接收暫存器中前一個已經收到的位元組之前,便能接收第二個位元組,如果第二個位元組已經接收完畢,第一個位元組還沒有被讀出,則第一個位元組就損失( 被覆蓋 )。而傳送器中的資料是由CPU控制的,所以不必程式使用者擔憂。

3  程式實現序列通訊

程式的大體框架為main主函式、序列中斷服務程式、子函式(初始化串列埠、延時函式,字串處理函式等)

(1)首先是用程式實現序列通訊的初始化

//串列埠初始化

void UART_Init(void)

{

         SCON  = 0x40;                   //串列埠方式1

         PCON  = 0;                     //SMOD=0

         REN  = 1;                               //允許接收

         TMOD = 0x20;                            //定時器1定時方式2

         TR1  = 1;                                   //啟動定時器

         ES  = 1;                                                              //UART中斷

         EA  = 1;                                                              //中斷使能

}

(2)用程式實現發資料

將要傳送的資料賦值給SBUF即可。

SBUF = aChar;

while(TI == 0);//等待,直到傳送成功

TI = 0;

這是傳送一次資料(如一個字元,在串列埠傳送方式1下佔10個位)的程式碼,可單獨寫成函式。此種寫法不可以將“TI = 0;”寫在中斷函式中,不然會造成死迴圈【執行一下程式碼便知】。

(3)在中斷函式中接受資料

不管傳送資料成功還是接受到資料都會進入到中斷程式中,故而在中斷程式中判斷是否RI被置位為1,如是則表示收到了資料。

void UART_Receive_Int() interrupt 4

{       

         if(  RI == 1)

         {

                   RI     = 0;           

                   if(  index < 1 )

                   {

                           Receive[index] = SBUF;

                            index++;

                   }else{

                            index  = 0;

                   }                

         }       

}

然後只需要在主程式main函式中呼叫序列口初始化函式及用一定的邏輯呼叫資料傳送函式即可。

(4)通過串列埠除錯助手來觀察程式執行效果

1】發資料顯示

設定串列埠除錯助手:

Figure2:向除錯助手發資料顯示

在串列埠除錯助手中按照下劃線部分設定後,結果顯示區域就會顯示由程式發將上來的資料。

【2】串列埠除錯助手往單片機發送資料並再顯示到串列埠除錯介面之上

Figure3:除錯助手向單片機發送資料顯示介面

對串列埠除錯助手的設定除了傳送資料之上的設定之外還需要在表格中填入字串,然後點選表格下畫圈使之為“停止迴圈傳送”,然後就可以將收到的資料同將要傳送的資料一起傳送到串列埠除錯介面之上來。

此次筆記記錄完畢。