1. 程式人生 > >【51微控制器】(手把手教你)串列埠通訊-基礎篇

【51微控制器】(手把手教你)串列埠通訊-基礎篇

通訊方式

並行

適合短距離通訊,並行通訊控制簡單、相對傳輸速度快(8位一起傳輸)。


序列

只能一位一位的傳送。


同步(瞭解)

建立傳送方時鐘對接收方時鐘的直接控制,使雙方達到完全同步。此時,傳輸資料的位之間的距離均為“位間隔”的整數倍,同時傳送的字元間不留間隙。

傳送方對接收方的同步可以通過外同步和自同步

非同步

以字元(構成的幀)為單位進行傳輸。資料位從低到高傳送。

格式:


這裡的空閒時間是任意的。

序列通訊的制式(傳輸方向)

單工(僅能沿一個方向)


半雙工(可進行雙向,但需分時)


全雙工


序列通訊的錯誤校驗

奇偶校驗

在傳送資料時,資料位尾隨的1位為奇偶校驗位(1/0)。奇校驗時,資料中1的個數與檢驗位1的個數之和應為奇數;偶校驗時,資料中1的個數與校驗位1的個數之和應為偶數。接收字元時,對1的個數進行校驗,若字元不一致,則說明傳輸資料過程中出現錯誤。

程式碼和校驗

傳送方將所發資料塊求和(或各位元組異或),產生一個位元組的校驗字元(校驗和)附加到資料塊末尾。接收方接收資料時,同時對資料塊(除校驗位元組外)求和(或各位元組異或),將所得的結果與傳送方的“校驗和”進行比較,一致則無差。

迴圈冗餘校驗

通過某種數學預算實現有效資訊與校驗位之間的迴圈校驗,常用語對磁碟資訊的傳輸、儲存區的完整性校驗。


串列埠的基本結構


SBUF:51微控制器中的特殊暫存器,序列資料緩衝器(一個接收一個傳送),兩個其實是共用的一個地址99H,但是兩個在物理上面是分開的。 傳送使用時,就採用SBUF=XXX;  (XXX為需要傳送的資料) 接收使用時,採用XXX=SBUF;
記得因為是序列的所以傳輸都是一位一位進行的。 T1溢位率:T1計時器的溢位頻率(就是計時器每次低位計滿向高位進位時間的倒數) 用處:用於計算波特率(每秒傳輸二進位制程式碼的位數)

實現微控制器與電腦之間的互相傳送字串通訊

工具:STC-ISP

程式碼:

#include <reg52.h>
#include <stdio.h>              //printf標頭檔案
#define uc unsigned char 
#define uint unsigned int

uc flag,i,flag_t,s[50]="",j=0,flag_n=0;
uc code table[]="I get ";        

void init()
{
	TMOD=0x20;	  //定時器工作方式,選擇了定時器1,工作方式2 八位初值自動重灌的8位定時器。		 
	TH1=0xfd;	  //定時器1初值	,設定波特率為9600 晶振11.0529MHZ?
	TL1=0xfd;
	TR1=1;		  //開啟定時器1

	SM0=0;
	SM1=1;		  //10位非同步接收,(8位資料)波特率可變
    REN=1;		  //允許序列口接收位
	EA=1;	      //允許中斷(總閘)
	ES=1;		  //允許串列埠中斷
}
void main()
{
	init();
	while(1)
{
	  if(flag==1)
	{	  if(flag_n!=0)		   //使第二個及以後I get xx 換行,不與You transfer在一行(單純為了格式好看)
			{TI=1;
			printf("\n");
			while(!TI);
			TI=0;
			}
		for(i=0;i<6;i++)
		{
			SBUF=table[i];
			while(!TI);
			TI=0;
		}
			for(i=0;s[i]!='#'&&i<50;i++)
		{
			SBUF=s[i];
			while(!TI);
			TI=0;
		}
		flag=0;
	}
	if(flag_t==1)						   //傳送完畢之後,在電腦端輸出。
	{
		TI=1;							   //printf之前必須將T1置為1才行。
		printf ("\nYou transfer %s",s);
		while(!TI);
		TI=0;
		flag_t=0;
	}	
}
}

void ser() interrupt 4
{
		if(RI)		 //接收資料,手動將RI清0
	{	    
		RI=0;
		
		if(flag==0&&j!=0)//1.迴圈賦值為'\0'(字串結尾標誌符),j=0,為了第二次傳遞字串是又是從頭輸出
		{			 //2.flag為0和j不為0時,保證是第二次及以後,傳輸字串(控制輸出格式)
			flag_n++;			 
			for(j=0;s[j]!='#'&&j<50;j++)
				  s[j]='\0';
				  j=0;
		}
		s[j]=SBUF;
		flag=1;
		if(s[j]=='#'||j==49)	 //以'#'作為傳送字串的結尾符,我定義的字元陣列最長為50所以49也應該結束。
			flag_t=1;
		else
		 	j++;
	}

	if(TI)     //傳送資料
	{
	}	 
}


執行截圖:


程式碼解讀:基本上就是幾個模組:計時器、中斷以及串列埠通訊

中斷

暫存器介紹

IE(interrupt enable):(可位定址)設定各個中斷源的開啟和關閉
IP(interrupt prior)中斷優先順序暫存器:(可位定址)用來設定各個中斷源屬於兩級中斷中的哪一級

中斷源:


中斷響應條件:

1.中斷源有中斷請求 2.此中斷源的中斷允許位為1 3.CPU開中斷(EA=1)

程式碼書寫:

1.先開總中斷EA 2 .然後再開特定的中斷去控制 3.如果有特殊需要優先順序問題再設定IP 4.中斷函式書寫 格式 void 函式名() interrupt 中斷號(上面圖示的序號) //中斷函式返回值一定是void   //函式名隨便寫 //中斷號用來判斷是哪個中斷源

計時器

暫存器介紹

TCON 支援位定址 :控制暫存器,控制T1、T0的啟動和停止及設定溢位標誌

TMOD,不支援位定址:定時/計數器的工作方式暫存器,確定工作方式和功能



計時器程式碼書寫步驟:

1.EA=1;

2.ETX=1;                            //開啟計時器X中斷 3.配置工作方式  TMOD=0x..; //根據自己需求按照上表來配     

3.配置計時器初值

//THX=(65535-N)/256; //TLX=(65535-N)%256;     //N由你要計時的時長決定。計時器計一個數花費一個時鐘週期來計算。 4.TRX=1;                           //開啟計時器X

串列埠通訊

暫存器介紹

PCON電源管理暫存器 :(不可位定址)

用來管理微控制器的電源部分,包括上電覆位檢測、掉電模式

、空閒模式等



SCON:(可位定址)用以設定序列口的工作方式、接收/傳送控制以及設定狀態標誌



波特率計算



SMOD就是PCON中的第一位,預設為0 fosc為晶振頻率,所以自己設定不同波特率時,也要考慮晶振不同的問題。

程式碼書寫

1.上面都書寫完畢之後 2.還需要ES=1 3.傳輸資料時,SBUF=XX    接收資料時,XX=SBUF 4.中斷函式書寫  一定要將RI清0,但是TI的清0在主函式中進行 //因為TI在中斷中進行,(1)沒有if(TI)的判斷,那麼就會和RI的處理混淆(2)如果有TI判斷 //那麼有可能永遠進行不了傳輸資料,因為最開始TI是為0的,無法進入TI條件,就無傳 //輸資料(SBUF=XX)。而且在傳輸資料的時候會又一次進入中斷,就是還沒處理中 //斷就又進入了另外一箇中斷,導致通訊出現異常。 相信有了這些模組的講解之後加上程式碼的註釋應該都懂了~ 如果有任何問題和不懂的都可以提出~