基于51的串行通讯原理及协议详解(uart)
生活随笔
收集整理的這篇文章主要介紹了
基于51的串行通讯原理及协议详解(uart)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
串行與并行通訊方式
并行:控制簡單,傳輸速度快。線多,長距離成本較高且同時接受困難。
串行:將數據字節分成一位一位的行駛在一條傳輸線上進行傳輸。如圖:
?
| 同步與異步串行通訊方式 同步串行通訊方式:同步通訊需要建立發送方對接收方時鐘的直接控制,是雙方達到完全同步。 異步串行通訊方式:通訊的發送和接收設備使用各自的時鐘控制數據的發送和接收,為使雙方收發協調,要求發送和接收的時鐘盡可能一致。如圖: 異步通訊方式的特點: 異步通訊以字符構成的幀為單位進行傳輸,字符與字符之間的間隙是任意的,但每個字符中的各位是以固定的時間傳送的。其一幀字符信息由4部分組成:起始位、數據位、奇偶檢驗位、停止位。在單片機中的通訊一般情況下均使用這種幀格式。如圖: 串行通訊的制式 單工:數據傳輸僅沿一個方向,不能實現反向傳輸 半雙工:數據可以沿兩個方向傳輸,但是需要分時 全雙工:數據可以同時進行雙向傳輸 串行通訊三種錯誤校驗:奇偶校驗、代碼和校驗、循環冗余校驗 RS232電平與TTL電平的轉換 PC使用的串口的電平為RS232的九針串口,MCU使用的電平是TTL電平,要使得PC 和MCU進行通訊,就需要對其電平極性轉換。主要的幾款電平轉換芯片:MAX232、MAX202、HIN232,SIPEX320等 串行通訊速度的定義_波特率 串行通訊的速率用波特率表示,其定義為: ?????????????????? 每秒鐘傳送二進制代碼的位數,即1波特=1位/秒,單位bps(位/秒) eg:每秒鐘傳送240個字符,而每個字符格式包含10位(1起始、8數據、1停止),此時的波特率為: ?????????????????? 10位*240個/秒=2400bps 串行通訊波特率的計算 單片機的串行口可設定為四種工作方式,其中方式0和方式2波特率固定,方式1和方式3波特率可變,由定時器T1的溢出率來決定。計算公式如下: 其中:fosc為系統晶振頻率,通常為12MHz(或者11.0592MHz),SMOD為PCON寄存器的最高位。T1的溢出率即定時器T1溢出的頻率。 電源管理寄存器_PCON SMOD;該位與串通信波特率有關。 SMOD=0;串口方式1、2、3時,波特率正常 SMOD=1;串口方式1、2、3時,波特率加倍 SMOD0,LVDF,P0F,此三位為STC_MCU 所特有的,可查看相關手冊。 GF1、GF0;兩個通用標志位,可隨意使用。 PD;掉電模式設定位, PD=0;MCU正常工作 PD=1;MCU進入掉電模式 IDL;空閑模式設定位 IDL=0;MCU正常工作 IDL=1;單片機進入空閑模式 單片機的兩種模式狀態: 掉電模式:進入掉電模式后,晶振停震,CPU,定時器,串行口全部停止工作,只有外部中斷繼續工作, 可有外部中斷低電平觸發或下降沿觸發或硬件復位模式喚醒。 空閑模式:除CPU不夠工作外,其余仍繼續工作,在空閑模式下,可由任一個中斷或者硬件復位喚醒 T1的溢出率 T1的溢出率就是T1定時器溢出的頻率,只要算出T1定時器每一處一次所需的時間T,那么T的倒數即為他的溢出率。 51串行口結構 51單片機串行口是一個可編程全雙工的通信接口,具有Uart(通用異步收發器)的全部功能,能同時進行數據的發送與接收,也可作為同步一位寄存器使用。 51_MCU主要由兩個獨立的串行數據緩沖寄存器SBUF (一個發送,一個接收)和發送控制器、接收控制器,輸入移位寄存器及若干控制門電路。如圖: 串行口控制寄存器_SCON SM0,SM1;工作方式選擇位,串口有四中工作方式,如下: SM2;多機通信可控制位,SM2主要用于方式2和方式3,當接收機的SM2=1時,可以利用收的RB8來控制是否激活RI; RB8=0,不激活RI,收到的信息丟棄 RB8=1,收到的數據進入SBUF,并激活RI,進而在中斷服務中將數據從SBUF讀走, 當SM2=0時,無論收到的RB8是0還是1,均可以收收到的數據進入SBUF,并激活RI,通過控制SM2可實現多機通信。 在方式0時,SM2必須是0, 在方式1時,若SM2=1,則只有接收到有效停止位時,RI才置1 REN;允許串行接收位 REN=1;允許串行口接收數據 REN=0;禁止串行口接收數據 TB8;方式2、3中發送數據的第九位,可定義其作用,奇偶檢驗,地址幀標志等,方式0和1中,未使用 RB8;方式2、3中接收數據的第九位,可定義其作用,奇偶檢驗,地址幀標志等,方式1,若SM2=0,則RB8是接收到的停止位。 TI;發送中斷標志位,方式0中,串行發送第8位數據結束時,或者其他方式,串行發送停止位時,由內部硬件置1,向CPU發出中斷申請,在中斷服務程序中,須用軟件清零,取消此中斷申請。 RI;接收中斷標志位, 方式0中,串行接收第8位數據結束時,或者其他方式,串行接收停止位時,由內部硬件置1,向CPU發出中斷申請,在中斷服務程序中,須用軟件清零,取消此中斷申請 串口方式0,串行口為同步移位寄存器的輸入輸出方式,主要永不擴展并行輸入輸出接口,數據由RXD(P3.0)引腳輸入或者輸出,同步移位脈沖由TXD(P3.1)引腳輸出,發送和接收均為8位數據,低位在先,高位在后。波特率固定fosc/12 串口方式1;10位數據一步通訊口,1起始,8數據,1停止,TXD(P3.1)為數據發送引腳,RXD(P3.0)為數據接收引腳。其傳輸波特率可變,對51而言,波特率有定時器1的溢出率而決定,一般而言,在單片基于單片機,單片機與計算機,計算機與計算機串口通訊時,基本都市選擇方式1,所以此種方式必須掌握。 串口方士2,3;11位數據的異步通訊口,XD(P3.1)為數據發送引腳,RXD(P3.0)為數據接收引腳。在這兩種方式下,1起始,9數據,1停止,一幀數據11位。方式2的波特率固定為晶晶振頻率的1/64或1/32,方式3的波特率由定時器1的溢出率決定。 方式2和方式2的差別僅在于波特率的選取不同,兩種方式下,接收到的停止位與SBUF,RB8,RI都無關。 串口方式1的編程實現 方式1數據輸出時序圖如下: 當數據被寫入SBUF寄存器后,單片機自動開始從起始位發送數據,發送到停止位的開始時, 由內部硬件將TI置1,向CPU申請中斷,接下來可在中斷服務程序中進行相關處理,也可選擇不進入中斷。 用軟件置REN為1時,接收器以所選擇波特率的16倍速率采樣RXD引腳電平, 檢測到RXD引腳輸入電平發聲負跳變時,則說明起始位有效。 將其移入輸入移位寄存器并開始接受這一幀信息的其余位。 接收過程中,數據從輸入移位寄存器右邊移入,起始位移至輸入移位寄存器的最左邊, 控制電路進行最后一次移位,當RI=0且SM2=0(或結收到的停止位為1)時, 將接受到的9位數據前8位數據裝入接收SBUF,第九位(停止位)進入RB8,并置RI=1,向CPU申請中斷, 在進行串口的相關操作之前,需要對單片機的一些特殊寄存器和進行初始化設置 主要是設置產生波特率的定時器1,串行口控制和中斷控制,具體步驟如下: 確定T1的工作方式(編程TMOD寄存器) 計算T1的初值,裝載TH1和TL1 啟動T1(編程TCON中的TR1位) 確定串行口工作方式(編程SCON寄存器) 串行口工作在中斷方式時,要進行中斷設置(編程IE、IP寄存器) ----------------------------------------------------------------------------------------------------------------------- //串口方式1 TMOD=0X20;??? //T1定時器,工作方式2 TH1=0XFD;??? //T1定時器裝初值 TL1=0XFD;??? //T1定時器裝初值 TR1=1;??? ??? //啟動T1定時器 REN=1;??? ??? //允許串口接收 SM0=0;??? ??? //設定串口工作方式1 SM1=1;??? ??? //設定串口工作方式1 EA=1;??? ??? //開總中斷 ES=1;??? ??? //開串口中斷 ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- //串口中斷服務程序 void ser() interrupt 4 { ??? RI=0;??? ??? ?? //RI清零;因為收到數據或者或者發送了數據會由硬件置1 ??? a=SBUF;??? ??? ?? //將SBUF中的數據讀走給a ??? flag=1;??? ??? ?? //中斷標志位置1 } ----------------------------------------------------------------------------------------------------------------------- 串口方式0 串行口為同步移位寄存器的輸入輸出方式,主要永不擴展并行輸入輸出接口,數據由RXD(P3.0)引腳輸入或者輸出,同步移位脈沖由TXD(P3.1)引腳輸出,發送和接收均為8位數據,低位在先,高位在后。波特率固定fosc/12。 在該模式下,串行口的SBUF是作為同步移位寄存器使用的。 在串行口發送時。SBUF相當于一個并行進入,串行輸出的移位寄存器, 由單片機的內部總線并行接收八位數據,并從RXD信號線串行輸出,在接收操作時,他有相當于一個串行輸入、并行輸出的移位寄存器。該模式下,SM2,RB8,TB8不起作用。 方式0數據輸出時序圖如下: 發送操作在TI=0時進行,CPU將數據移入SBUF后,RXD線上即可發出8位數據,TXD上發送同步脈沖, 8位數據發送完后,TI由硬件置位,并在中斷允許的情況下向CPU申請中斷, CPU相應中斷后,先用軟件是TI清零,然后再給SBUF送下一個需要發送的字符,如此重復上述過程。 方式0數據輸入時序圖如下: 接收過程在REN=1和RI=0的條件下啟動,為此串行數據由RXD線輸入,TXD線輸出同步脈沖, 接收電路接收到8位數據后,RI自動置位并在中斷允許的條件下向CPU發出中斷請求, CPU 查詢到RI為1或者相應中斷以后便將SBUF中的數據送到累加器,RI需要由軟件復位, 需要注意的是: 串行口工作模式0并不是一個同步通訊串口通訊方式, 它的主要用途是與外面的同步移位寄存器相連已達到擴展單片機輸入并行口和輸出并行口的目的。 其可以通過芯片(74LS164)把串口數據轉化成并口數據,通過芯片(74LS165)把并行輸出的數據轉換成串口輸出 ----------------------------------------------------------------------------------------------------------------------- 使用串口工作模式0間隔發送數據0XAA void main() { ??? SCON=0;??? ?? ??? ??? //串行口工作方式0 ??? EA=1;??? ??? ??? //開總中斷 ??? ES=1;??? ??? ??? //允許串口中斷 ??? TI=0;??? ??? ??? //發送中斷標志位 ??? while(1) ??? { ??? ??? SBUF=0XAA;??? ??? ??? delay(); ??? } } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- void ser0() interrupt 4 { ??? TI=0;??? ??? //清楚發送中斷標志位 } ----------------------------------------------------------------------------------------------------------------------- 串口方式2和方式3 均為11位數據的異步通信口,唯一的區別在于傳輸速率的不同。 TXD數據發送引腳,RXD數據接收引腳,1起始, 9數據(含1位附加第9位,發送時為SCON中的TB8,接收時為RB8),1停止,一幀數據11位。 方式2的波特率固定為晶晶振頻率的1/64或1/32,方式3的波特率由定時器1的溢出率決定。 串口方式2和方式3一幀數據傳送格式,如圖: 串口方式2和方式3輸出時序圖: 發送開始時,先把起始位0輸出到TXD管腳,然后發送移位寄存器的的輸出位(D0)到TXD引腳 每一個移位脈沖都使輸出移位寄存器的各位右移一位,并由TXD引腳輸出, 第一次移位時,停止位1移入輸出移位寄存器的第9位,以后每次移位,左邊都輸入0 當停止移位至輸出位時,左邊其余位全為零,檢測電路檢測到這一條件時,使控制電路進行最后一次移位,并置TI=1;向CPU請求中斷。 串口方式2和方式3輸入時序圖: 接受時,數據從右邊移入輸入移位寄存器,在起始位0移到最左邊時,控制電路進行最后一次移位。 當RI=0且SM2=0(或接收到第9位數據位1)時,接收到的數據裝入接收緩沖器SBUF和RB8(接收數據的第9位),置RI=1,向CPU申請中斷,如果條件不滿足,則數據丟失,且不置位RI,繼續搜索RXD引腳的負跳變。 在方式2和方式3中,要用到SCON寄存器中的TB8位和RB8位,TB8為數據發送的第9位,用于方式2和方式3,由軟件更改,RB8為數據接收的第9位,用于方式2和方式3,在方式1中,如果SM2=0,則RB8用于存放接收到的停止位,在方式0下不適用該位。 ----------------------------------------------------------------------------------------------------------------------- 使用串口工作方式2發送0XAA void main() { ??? SM0=1;??? ??? ??? //SMOSM1為10,串行工作方式2 ??? SM1=0;??? ??? ??? //11位異步收發(9位數據) ??? TB8=0;??? ??? ??? //數據發送的第9位 ??? EA=1;??? ??? ??? //開總中斷 ??? ES=1;??? ??? ??? //允許串口中斷 ??? TI=0;??? ??? ??? //發送中斷標志位 ??? while(1) ??? { ??? ??? SBUF=0XAA;??? ??? ??? delay(); ??? } } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- void ser0() interrupt 4 { ??? TI=0;??? ??? //清楚發送中斷標志位 } ----------------------------------------------------------------------------------------------------------------------- 單片機雙機通信 通常單片機通信有以下四種實現方式: TTL電平通信 RS-232C通信 RS-422A通信 RS-485通信 TTL電平通信: RS-232C通信: RS-422A通信 RS-422A驅動器為雙端驅動器,其中一條線的邏輯為1,另一條線就為0, 具抗干擾型,能夠200mv以上的電位差, 傳輸速率90Kbps,傳輸距離可達1200m,接口電路如下:(全雙工) RS-485通信 RS-485是RS-422A的變種,422A是全雙工,485為半雙工, 最多可使用32對差分器。如在一個網絡中連接超過32個,還可使用中繼器。 引起傳輸線采用差動信號,所以抗干擾性好,傳輸速率可達1Mbps,接口如下: 多機通信 采用主從結構,在整個系統中,有且僅有一個主機,其余全是從機,多機通信所應遵循的原則如下: A.所有從機的SM2=1;處于接收地址幀狀態 B.主機發送一地址幀,其中8位是地址,第9位是地址/數據區分標志,該位置1表示地址幀。 所有從機收到地址幀后,與本季的地址比較,對于地址相符的從機, 是自己的SM2置0(已接收主機隨后發來的數據幀),并把本機地址發回主機作為應答, 對于地址不符的,仍保持SM2=1,對主機隨后發來的數據幀不予理睬. C.從機發送數據結束后,要發送一幀校驗和,并置第9位(TB8)為1,作為從機數據結束的標志。 D.主機驗證數據時,先判斷數據接收標志(RB8),若RB8=1;表示數據傳送結束,并比較此幀校驗和, 若正確則會送正確信號00H,命令該從機復位(即重新等待地址幀)。 若校驗和出錯,則發送0FFH,命令該從機重發數據。 若接受偵的RB8=0;則將數據存到緩存區,并準備接收下一幀信息。 E.主機接到從機應答地址后,確認地址是否相符,如果地址不符, 則發復位信號(數據幀中TB8=1),如果地址相符,則TB8清0,開始發送數據。 從機收到復位命令后,會到監聽地址狀態(SM2=1),否則開始接收數據和命令。 編程時,可按以下方式操作: 主機發送的地址聯絡信號為00H,01H,02H,...(即從機設備地址);地址FFH為命令各從機復位,即回復SM2=1; 主機命令編碼如下: 01H:主機命令從機接收數據; 02H:主機命令從機發送數句; 若有其他數據,則都按02H對待。 從機狀態字格式如圖: 若ERR =1;從機收到非法命令。 若TRDY=1;從機發送準備就緒 若RRDY=1;從機接收準備就緒 通常,從機以中斷方式控制和主機通訊。 多機通信主機流程圖如下: 程序代碼如下: ----------------------------------------------------------------------------------------------------------------------- #include #define? uchar unsigned char #define uint unsigned int #define SLAVE 0X02?? //從機地址 #define? NB 16 uchar rbuf[16]; uchar code tbuf[16]={"master transmit"}; void err() { ??? SBUF=0XFF; ??? while(!TI=1); ??? TI=0; } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- uchar master(uchar add,uchar com) { ??? while(1) ??? { ??? ??? SBUF=SLAVE;??? ??? ??? //發呼叫地址 ??? ??? while(!TI=1); ??? ??? TI=0; ??? ??? while(!RI=1); ??? ??? RI=0;??? ??? ??? ??? //等待從機應答 ??? ??? if(SBUF!=add) ??? ??? { ??? ??? ??? err();??? ??? ??? //地址錯誤,發復位信號 ??? ??? }??? ??? ? ??? ??? else??? ??? ??? ??? //地址相符 ??? ??? { ??? ??? ??? TB8=0;??? ??? ??? //清地址標志 ??? ??? ??? SBUF=cmd;??? ??? //發命令 ??? ??? ??? while(!TI=1); ??? ??? ??? TI=0; ??? ??? ??? while(!RI=1); ??? ??? ??? RI=0; ??? ??? ??? aa=SBUF;??? ??? //接收狀態 ??? ??? ??? if(aa&0x08==0x08)??? ??? //若命令未被接收,發復位信號 ??? ??? ??? { ??? ??? ??? ??? TB8=1; ??? ??? ??? ??? err(); ??? ??? ??? } ??? ??? ??? else ??? ??? ??? { ??? ??? ??? ??? if(cmd==0X01)??? ??? ? //發送命令 ??? ??? ??? ??? { ??? ??? ??? ??? ??? if(aa&0x01==0x01)??? ?//從機準備好接受 ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? do ??? ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? ??? p=0;??? ??? ??? ? //清校驗和 ??? ??? ??? ??? ??? ??? ??? for(i=0;i ??? ??? ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? ??? ??? SBUF=tbuf[i];??? //發送一數據 ??? ??? ??? ??? ??? ??? ??? ??? p+=tbuf[i]; ??? ??? ??? ??? ??? ??? ??? ??? while(!TI=1); ??? ??? ??? ??? ??? ??? ??? ??? TI=0; ??? ??? ??? ??? ??? ??? ??? } ??? ??? ??? ??? ??? ??? ??? SBUF=p;??? ??? ??? //發送檢驗和 ??? ??? ??? ??? ??? ??? ??? while(!TI=1); ??? ??? ??? ??? ??? ??? ??? TI=0; ??? ??? ??? ??? ??? ??? ??? while(!RI=1); ??? ??? ??? ??? ??? ??? ??? RI=0; ??? ??? ??? ??? ??? ??? } ??? ??? ??? ??? ??? ??? while(SBUF!=0);??? ??? //接收不正確,重新發送 ??? ??? ??? ??? ??? ??? TB8=1;??? ??? ??? ??? //置地址標志 ??? ??? ??? ??? ??? ??? return(0); ??? ??? ??? ??? ??? } ??? ??? ??? ??? ??? else ??? ??? ??? ??? ??? if(aa&0x02==0x02)??? ??? //是接收命令,從機準備好發送 ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? while(1) ??? ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? ??? p=0;??? ??? //清檢驗和 ??? ??? ??? ??? ??? ??? ??? for(i=0;i ??? ??? ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? ??? ??? while(!RI=1); ??? ??? ??? ??? ??? ??? ??? ??? RI=0; ??? ??? ??? ??? ??? ??? ??? ??? rbuf[i]=SBUF;??? ??? //接收一數據 ??? ??? ??? ??? ??? ??? ??? ??? p+=rbuf[i]; ??? ??? ??? ??? ??? ??? ??? } ??? ??? ??? ??? ??? ??? ??? while(!RI=1); ??? ??? ??? ??? ??? ??? ??? RI=0; ??? ??? ??? ??? ??? ??? ??? if(SBUF==p) ??? ??? ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? ??? ??? SBUF=0x00;??? ??? ??? //校驗和相同發0X00 ??? ??? ??? ??? ??? ??? ??? ??? while(!TI=1); ??? ??? ??? ??? ??? ??? ??? ??? TI=0; ??? ??? ??? ??? ??? ??? ??? ??? break; ??? ??? ??? ??? ??? ??? ??? } ??? ??? ??? ??? ??? ??? ??? else ??? ??? ??? ??? ??? ??? ??? { ??? ??? ??? ??? ??? ??? ??? ??? SBUF=0xFF; ??? ??? ??? ??? ??? ??? ??? ??? while(!TI=1); ??? ??? ??? ??? ??? ??? ??? ??? TI=0; ??? ??? ??? ??? ??? ??? ??? } ??? ??? ??? ??? ??? ??? } ??? ??? ??? ??? ??? ??? TB8=1;??? ? ??? ??? //置地址標志 ??? ??? ??? ??? ??? ??? return(0); ??? ??? ??? ??? ??? } ??? ??? ??? ??? } ??? ??? ??? } ??? ??? } ??? } } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- void main() { ??? TMOD=0x20;??? //T/C1定義為方式2 ??? TL1=0XFD;??? //置初值 ??? TH1=0XFD; ??? PCON=0X00; ??? TR1=1; ??? SCON=0XF0;??? //串行口方式3 ??? master(SLAVE,0x01); ??? master(SLAVE,0X02); ??? while(1); } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- 多機通信從機流程圖: 程序如下: ----------------------------------------------------------------------------------------------------------------------- #include #define uchar unsigned char #define uint unsigned int #define? SLAVE 0X02 #define BN? 16 uchar trbuf[16]; uchar rebuf[16]; bit tready; bit rready; void str(void); void sre(void); void main() { ???? TMOD=0x20;??? ??? ??? //T/C1定義為方式2 ??? TH1=0XFD; ??? TL1=0XFD; ??? PCON=0X00; ??? TR1=1; ??? SCON=0XF0; ??? ES=1;??? ?//開串行口中斷 ??? EA=1;??? ?//開總中斷 ??? while(1) ??? { ??? ??? tready=1; ??? ??? rready=1;??? ??? }??? ??? ?//假定準備好發送和接受 } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- void ssio(void) interrupt 4 { ??? uchar a; ??? RI=0; ??? ES=0; ??? if(SBUF!=SLAVE) ??? { ??? ??? ES=1; ??? ??? goto reti; ??? }??? ??? ??? ? ??? ??? //非本機地址繼續監聽 ??? SM2=0;??? ??? ??? ??? //取消監聽狀態 ??? SBUF=SLAVE;??? ??? ??? //從本地址發回 ??? while(!TI=1); ??? TI=0; ??? while(!RI=1); ??? RI=0; ??? if(RB8=1) ??? { ??? ??? SM2=1; ??? ??? ES=1; ??? ??? goto reti; ??? }??? ??? ??? ? ??? ??? //是復位信號,恢復監聽 ??? a=SBUF;??? ??? ??? ??? //接收命令 ??? if(a==0X01) ??? { ??? ??? if(rready=1) ??? ??? ??? SBUF=0X01;??? ??? //接收準備好發狀體 ??? ??? else ??? ??? ??? SBUF=0X00; ??? ??? while(!TI=1); ??? ??? TI=0; ??? ??? while(!RI=1); ??? ??? RI=0; ??? ??? if(RB8==1) ??? ??? { ??? ??? ??? SM2=1; ??? ??? ??? ES=1; ??? ??? ??? goto reti; ??? ??? } ??? ??? sre();??? ??? ??? //接收數據 ??? } ??? else ??? { ??? ??? if(a==0X02)??? ??? ??? //從機向主機發送數據 ??? ??? { ??? ??? ??? if(tready=1) ??? ??? ??? ??? SBUF=0X02;??? ??? //發送準備好發狀體 ??? ??? ??? else ??? ??? ??? ??? SBUF=0X00; ??? ??? ??? while(!TI=1); ??? ??? ??? TI=0; ??? ??? ??? while(!RI=1); ??? ??? ??? RI=0; ??? ??? ??? if(RB8==1) ??? ??? ??? { ??? ??? ??? ??? SM2=1; ??? ??? ??? ??? ES=1; ??? ??? ??? ??? goto reti; ??? ??? ??? } ??? ??? ??? str();??? ??? ??? //發送數據 ??? ??? } ??? ??? else ??? ??? { ??? ??? ??? SBUF=0X80;??? ??? ??? //命令非法,發狀態 ??? ??? ??? while(!TI=1); ??? ??? ??? TI=0; ??? ??? ??? SM2=1; ??? ??? ??? ES=1; ??? ??? ??? //恢復監聽 ??? ??? }??? ??? } ??? reti; } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- void str(void)??? ??? ??? //發送數據塊 { ??? uchr p,i; ??? tready=0; ??? do ??? { ??? ??? p=0;??? ??? //清校驗和 ??? ??? for(i=0;i ??? ??? { ??? ??? ??? SBUF=trbuf[i];??? ??? ??? //發送一數據 ??? ??? ??? p+=trbuf[i]; ??? ??? ??? while(!TI=1); ??? ??? ??? TI=0; ??? ??? } ??? ??? SBUF=p; ??? ??? ??? //發送校驗和 ??? ??? while(!TI=1); ??? ??? TI=0; ??? ??? while(!RI=1); ??? ??? RI=0; ??? }while(SBUF!=0);??? ??? //主機接收不正確,從新發送 ??? SM2=1; ??? ES=1;??? } ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- void sre(void)??? ??? ? ??? ??? //接收數據塊 { ??? uchr p,i; ??? rready=0; ??? while(1) ??? { ??? ??? p=0;??? ??? //清校驗和 ??? ??? for(i=0;i ??? ??? { ??? ??? ??? while(!RI=1); ??? ??? ??? RI=0; ??? ??? ??? rebuf[i]=SBUF;??? ??? //接收數據 ??? ??? ??? p+=rebuf[i]; ??? ??? } ??? ??? while(!RI=1); ??? ??? RI=0; ??? ??? if(SBUF==p) ??? ??? { ??? ??? ??? SBUF=0X00; ??? ??? ??? break; ??? ??? }??? ??? ? //校驗和相同發00 ??? ??? else ??? ??? { ??? ??? ??? SBUF=0XFF;??? ?? ??? //校驗值不同發0FF,重新接收 ??? ??? ??? while(!TI=1); ??? ??? ??? TI=0; ??? ??? } ??? } ??? SM2=1; ??? ES=1;??? ??? } ----------------------------------------------------------------------------------------------------------------------- 以上是51串口的通訊的協議內容,也可以說是串口通訊協議。其與Uart等具有相同的傳輸性質:雙向傳輸,全雙工! |
轉載于:https://www.cnblogs.com/hulianxingkong/p/9096733.html
總結
以上是生活随笔為你收集整理的基于51的串行通讯原理及协议详解(uart)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Canny边缘检测算法原理及其VC实现详
- 下一篇: python连接阿里云服务器_阿里云服务