RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

串口通信的原理,IO口模擬UART串口通信

GReq_mcu168 ? 來源:未知 ? 作者:李倩 ? 2018-05-04 15:26 ? 次閱讀

串口通信的原理

串口通信(SerialCommunicaTIons)的概念非常簡單,串口按位(bit)發(fā)送和接收字節(jié)。盡管比按字節(jié)(byte)的并行通信慢,但是串口可以在使用一根線發(fā)送數(shù)據(jù)的同時(shí)用另一根線接收數(shù)據(jù)。它很簡單并且能夠?qū)崿F(xiàn)遠(yuǎn)距離通信。比如IEEE488定義并行通行狀態(tài)時(shí),規(guī)定設(shè)備線總長不得超過20米,并且任意兩個(gè)設(shè)備間的長度不得超過2米;而對于串口而言,長度可達(dá)1200米。典型地,串口用于ASCII碼字符的傳輸。通信使用3根線完成,分別是地線、發(fā)送、接收。由于串口通信是異步的,端口能夠在一根線上發(fā)送數(shù)據(jù)同時(shí)在另一根線上接收數(shù)據(jù)。其他線用于握手,但不是必須的。串口通信最重要的參數(shù)是波特率、數(shù)據(jù)位、停止位和奇偶校驗(yàn)。對于兩個(gè)進(jìn)行通信的端口,這些參數(shù)必須匹配。

串口通信的原理,IO口模擬UART串口通信

a,波特率:這是一個(gè)衡量符號傳輸速率的參數(shù)。指的是信號被調(diào)制以后在單位時(shí)間內(nèi)的變化,即單位時(shí)間內(nèi)載波參數(shù)變化的次數(shù),如每秒鐘傳送240個(gè)字符,而每個(gè)字符格式包含10位(1個(gè)起始位,1個(gè)停止位,8個(gè)數(shù)據(jù)位),這時(shí)的波特率為240Bd,比特率為10位*240個(gè)/秒=2400bps。一般調(diào)制速率大于波特率,比如曼徹斯特編碼)。通常電話線的波特率為14400,28800和36600。波特率可以遠(yuǎn)遠(yuǎn)大于這些值,但是波特率和距離成反比。高波特率常常用于放置的很近的儀器間的通信,典型的例子就是GPIB設(shè)備的通信。

b,數(shù)據(jù)位:這是衡量通信中實(shí)際數(shù)據(jù)位的參數(shù)。當(dāng)計(jì)算機(jī)發(fā)送一個(gè)信息包,實(shí)際的數(shù)據(jù)往往不會是8位的,標(biāo)準(zhǔn)的值是6、7和8位。如何設(shè)置取決于你想傳送的信息。比如,標(biāo)準(zhǔn)的ASCII碼是0~127(7位)。擴(kuò)展的ASCII碼是0~255(8位)。如果數(shù)據(jù)使用簡單的文本(標(biāo)準(zhǔn)ASCII碼),那么每個(gè)數(shù)據(jù)包使用7位數(shù)據(jù)。每個(gè)包是指一個(gè)字節(jié),包括開始/停止位,數(shù)據(jù)位和奇偶校驗(yàn)位。由于實(shí)際數(shù)據(jù)位取決于通信協(xié)議的選取,術(shù)語“包”指任何通信的情況。

c,停止位:用于表示單個(gè)包的最后一位。典型的值為1,1.5和2位。由于數(shù)據(jù)是在傳輸線上定時(shí)的,并且每一個(gè)設(shè)備有其自己的時(shí)鐘,很可能在通信中兩臺設(shè)備間出現(xiàn)了小小的不同步。因此停止位不僅僅是表示傳輸?shù)慕Y(jié)束,并且提供計(jì)算機(jī)校正時(shí)鐘同步的機(jī)會。適用于停止位的位數(shù)越多,不同時(shí)鐘同步的容忍程度越大,但是數(shù)據(jù)傳輸率同時(shí)也越慢。

d,奇偶校驗(yàn)位:在串口通信中一種簡單的檢錯(cuò)方式。有四種檢錯(cuò)方式:偶、奇、高和低。當(dāng)然沒有校驗(yàn)位也是可以的。對于偶和奇校驗(yàn)的情況,串口會設(shè)置校驗(yàn)位(數(shù)據(jù)位后面的一位),用一個(gè)值確保傳輸?shù)臄?shù)據(jù)有偶個(gè)或者奇?zhèn)€邏輯高位。例如,如果數(shù)據(jù)是011,那么對于偶校驗(yàn),校驗(yàn)位為0,保證邏輯高的位數(shù)是偶數(shù)個(gè)。如果是奇校驗(yàn),校驗(yàn)位為1,這樣就有3個(gè)邏輯高位。高位和低位不真正的檢查數(shù)據(jù),簡單置位邏輯高或者邏輯低校驗(yàn)。這樣使得接收設(shè)備能夠知道一個(gè)位的狀態(tài),有機(jī)會判斷是否有噪聲干擾了通信或者是否傳輸和接收數(shù)據(jù)是否不同步。

RS232概述

在我們電腦上,一般都會有一個(gè)9針的串行接口,這個(gè)串行接口叫做RS232接口,它和UART通信有關(guān)聯(lián),但是由于現(xiàn)在筆記本電腦不帶9針串口,所以和單片機(jī)通信越來越趨于使用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個(gè)引腳,分別定義是:1、載波檢測DCD;2、接收數(shù)據(jù)RXD;3、發(fā)送數(shù)據(jù)TXD;4、數(shù)據(jù)終端準(zhǔn)備好DTR;5、信號地線SG;6、數(shù)據(jù)準(zhǔn)備好DSR;7、請求發(fā)送RTS;8、清除發(fā)送CTS;9、振鈴提示RI。我們要讓這個(gè)串口和我們單片機(jī)進(jìn)行通信,我們只需要關(guān)心其中的2腳RXD、3腳TXD和5腳GND即可

雖然這三個(gè)引腳的名字和我們單片機(jī)上的串口名字一樣,但是卻不能直接和單片機(jī)對連通信,這是為什么呢?隨著我們了解的內(nèi)容越來越多,我們得慢慢知道,不是所有的電路都是5V代表高電平而0V代表低電平的。對于RS232標(biāo)準(zhǔn)來說,它是個(gè)反邏輯,也叫做負(fù)邏輯。為何叫負(fù)邏輯?它的TXD和RXD的電壓,-3V~-15V電壓代表是1,+3~+15V電壓代表是0。低電平代表的是1,而高電平代表的是0,所以稱之為負(fù)邏輯。因此電腦的9針RS232串口是不能和單片機(jī)直接連接的,需要用一個(gè)電平轉(zhuǎn)換芯片MAX232來完成

這個(gè)芯片就可以實(shí)現(xiàn)把標(biāo)準(zhǔn)RS232串口電平轉(zhuǎn)換成我們單片機(jī)能夠識別和承受的UART0V/5V電平。從這里大家似乎慢慢有點(diǎn)明白了,其實(shí)RS232串口和UART串口,它們的協(xié)議類型是一樣的,只是電平標(biāo)準(zhǔn)不同而已,而MAX232這個(gè)芯片起到的就是中間人的作用,它把UART電平轉(zhuǎn)換成RS232電平,也把RS232電平轉(zhuǎn)換成UART電平,從而實(shí)現(xiàn)標(biāo)準(zhǔn)RS232接口和單片機(jī)UART之間的通信連接。

USB轉(zhuǎn)串口通信

隨著技術(shù)的發(fā)展,工業(yè)上還有RS232串口通信的大量使用,但是商業(yè)技術(shù)的應(yīng)用上,已經(jīng)慢慢的使用USB轉(zhuǎn)UART技術(shù)取代了RS232串口,絕大多數(shù)筆記本電腦已經(jīng)沒有串口這個(gè)東西了,那我們要實(shí)現(xiàn)單片機(jī)和電腦之間的通信該怎么辦呢?

們只需要在電路上添加一個(gè)USB轉(zhuǎn)串口芯片,就可以成功實(shí)現(xiàn)USB通信協(xié)議和標(biāo)準(zhǔn)UART串行通信協(xié)議的轉(zhuǎn)換,在我們的開發(fā)板上,我們使用的是CH340T這個(gè)芯片

我們需要用跳線帽把中間和下邊的針短接在一起。右側(cè)的CH340T這個(gè)電路很簡單,把電源、晶振接好后,6腳和7腳的DP和DM分別接USB口的2個(gè)數(shù)據(jù)引腳上去,3腳和4腳通過跳線接到了我們單片機(jī)的TXD和RXD上去。

CH340T的電路里3腳位置加了個(gè)4148的二極管,是一個(gè)小技巧。因?yàn)镾TC89C52這個(gè)單片機(jī)下載程序時(shí)需要冷啟動(dòng),就是先點(diǎn)下載后上電,上電瞬間單片機(jī)會先檢測需要不需要下載程序。雖然單片機(jī)的VCC是由開關(guān)來控制,但是由于CH340T的3腳是輸出引腳,如果沒有此二極管,開關(guān)后級單片機(jī)在斷電的情況下,CH340T的3腳和單片機(jī)的P3.0(即RXD)引腳連在一起,有電流會通過這個(gè)引腳流入后級電路并且給后級的電容充電,造成后級有一定幅度的電壓,這個(gè)電壓值雖然只有兩三伏左右,但是可能會影響到正常的冷啟動(dòng)。加了二極管后,一方面不影響通信,另外一個(gè)方面還可以消除這種不良影響。這個(gè)地方可以暫時(shí)作為了解,大家如果自己做這類電路,可以參考一下。

IO口模擬UART串口通信

UART串口波特率,常用的值是300、600、1200、2400、4800、9600、14400、19200、28800、38400、57600、115200等速率。IO口模擬UART串行通信程序是一個(gè)簡單的演示程序,我們使用串口調(diào)試助手下發(fā)一個(gè)數(shù)據(jù),數(shù)據(jù)加1后,再自動(dòng)返回。

串口調(diào)試助手,這里我們直接使用STC-ISP軟件自帶的串口調(diào)試助手,先把串口調(diào)試助手的使用給大家說一下,如圖11-6所示。第一步要選擇串口助手菜單,第二步選擇十六進(jìn)制顯示,第三步選擇十六進(jìn)制發(fā)送,第四步選擇COM口,這個(gè)COM口要和自己電腦設(shè)備管理器里的那個(gè)COM口一致,波特率按我們程序設(shè)定好的選擇,我們程序中讓一個(gè)數(shù)據(jù)位持續(xù)時(shí)間是1/9600秒,那這個(gè)地方選擇波特率就是選9600,校驗(yàn)位選N,數(shù)據(jù)位8,停止位1。

串口調(diào)試助手的實(shí)質(zhì)就是利用電腦上的UART通信接口,發(fā)送數(shù)據(jù)給我們的單片機(jī),也可以把我們的單片機(jī)發(fā)送的數(shù)據(jù)接收到這個(gè)調(diào)試助手界面上。

因?yàn)槌醮谓佑|通信方面的技術(shù),所以我把后面的IO模擬串口通信程序進(jìn)行一下解釋,大家可以邊看我的解釋邊看程序,把底層原理先徹底弄懂。

變量定義部分就不用說了,直接看main主函數(shù)。首先是對通信的波特率的設(shè)定,在這里我們配置的波特率是9600,那么串口調(diào)試助手也得是9600。配置波特率的時(shí)候,我們用的是定時(shí)器T0的模式2。模式2中,不再是TH0代表高8位,TL0代表低8位了,而只有TL0在進(jìn)行計(jì)數(shù),當(dāng)TL0溢出后,不僅僅會讓TF0變1,而且還會將TH0中的內(nèi)容重新自動(dòng)裝到TL0中。這樣有一個(gè)好處,就是我們可以把想要的定時(shí)器初值提前存在TH0中,當(dāng)TL0溢出后,TH0自動(dòng)把初值就重新送入TL0了,全自動(dòng)的,不需要程序中再給TL0重新賦值了,配置方式很簡單,大家可以自己看下程序并且計(jì)算一下初值。

波特率設(shè)置好以后,打開中斷,然后等待接收串口調(diào)試助手下發(fā)的數(shù)據(jù)。接收數(shù)據(jù)的時(shí)候,首先要進(jìn)行低電平檢測while(PIN_RXD),若沒有低電平則說明沒有數(shù)據(jù),一旦檢測到低電平,就進(jìn)入啟動(dòng)接收函數(shù)StartRXD()。接收函數(shù)最開始啟動(dòng)半個(gè)波特率周期,初學(xué)可能這里不是很明白。大家回頭看一下我們的圖11-2里邊的串口數(shù)據(jù)示意圖,如果在數(shù)據(jù)位電平變化的時(shí)候去讀取,因?yàn)闀r(shí)序上的誤差以及信號穩(wěn)定性的問題很容易讀錯(cuò)數(shù)據(jù),所以我們希望在信號最穩(wěn)定的時(shí)候去讀數(shù)據(jù)。除了信號變化的那個(gè)沿的位置外,其它位置都很穩(wěn)定,那么我們現(xiàn)在就約定在信號中間位置去讀取電平狀態(tài),這樣能夠保證我們讀的一定是正確的。

一旦讀到了起始信號,我們就把當(dāng)前狀態(tài)設(shè)定成接收狀態(tài),并且打開定時(shí)器中斷,第一次是半個(gè)周期進(jìn)入中斷后,對起始位進(jìn)行二次判斷一下,確認(rèn)一下起始位是低電平,而不是一個(gè)干擾信號。以后每經(jīng)過1/9600秒進(jìn)入一次中斷,并且把這個(gè)引腳的狀態(tài)讀到RxdBuf里邊。等待接收完畢之后,我們再把這個(gè)RxdBuf加1,再通過TXD引腳發(fā)送出去,同樣需要先發(fā)一位起始位,然后發(fā)8個(gè)數(shù)據(jù)位,再發(fā)結(jié)束位,發(fā)送完畢后,程序運(yùn)行到while(PIN_RXD),等待第二輪信號接收的開始。

uart模塊介紹

IO口模擬串口通信,讓大家了解了串口通信的本質(zhì),但是我們的單片機(jī)程序卻需要不停的檢測掃描單片機(jī)IO口收到的數(shù)據(jù),大量占用了單片機(jī)的運(yùn)行時(shí)間。這時(shí)候就會有聰明人想了,其實(shí)我們并不是很關(guān)心通信的過程,我們只需要一個(gè)通信的結(jié)果,最終得到接收到的數(shù)據(jù)就行了。這樣我們可以在單片機(jī)內(nèi)部做一個(gè)硬件模塊,讓它自動(dòng)接收數(shù)據(jù),接收完了,通知我們一下就可以了,我們的51單片機(jī)內(nèi)部就存在這樣一個(gè)UART模塊,要正確使用它,當(dāng)然還得先把對應(yīng)的特殊功能寄存器配置好。

51單片機(jī)的UART串口的結(jié)構(gòu)由串行口控制寄存器SCON、發(fā)送和接收電路三部分構(gòu)成,先來了解一下串口控制寄存器SCON。

SCON串行控制器的位分配(地址:0x98)

位:符號:復(fù)位值: 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:接收中斷標(biāo)志位,當(dāng)接收電路接收到停止位的中間位置時(shí),RI由硬件置1,必須通過軟件清零

1位TI:發(fā)送中斷標(biāo)志位,當(dāng)發(fā)送電路發(fā)送到停止位的中間位置時(shí),TI由硬件置1,必須通過軟件清零。

2位RB8:模式2和3中接收到的第9位數(shù)據(jù)(很少用),模式1用來接收停止位。

3位TB8:模式2和3中要發(fā)送的第9位數(shù)據(jù)(很少用)。

4位REN:使能串行接收。由軟件置位使能接收,軟件清零則禁止接收。

5位SM2:多機(jī)通信控制位(極少用),模式1直接清零。

6位SM1和7位SM0:

這兩位共同決定了串口通信的模式0~模式3共4種模式。我們最常用的就是模式1,也就是SM0=0,SM1=1,下邊我們重點(diǎn)就講模式1,其它模式從略。

對于串口的四種模式,模式1是最常用的,就是我們前邊提到的1位起始位,8位數(shù)據(jù)位和1位停止位。下面我們就詳細(xì)介紹模式1的工作細(xì)節(jié)和使用方法,至于其它3種模式與此也是大同小異,真正遇到需要使用的時(shí)候大家再去查閱相關(guān)資料就行了。

在我們使用IO口模擬串口通信的時(shí)候,串口的波特率是使用定時(shí)器T0的中斷體現(xiàn)出來的。在硬件串口模塊中,有一個(gè)專門的波特率發(fā)生器用來控制發(fā)送和接收數(shù)據(jù)的速度。對于STC89C52單片機(jī)來講,這個(gè)波特率發(fā)生器只能由定時(shí)器T1或定時(shí)器T2產(chǎn)生,而不能由定時(shí)器T0產(chǎn)生,這和我們模擬的通信是完全不同的概念。

如果用定時(shí)器2,需要配置額外的寄存器,默認(rèn)是使用定時(shí)器1的,我們本章內(nèi)容主要就使用定時(shí)器T1作為波特率發(fā)生器來講解,方式1下的波特率發(fā)生器必須使用定時(shí)器T1的模式2,也就是自動(dòng)重裝載模式,定時(shí)器的重載值計(jì)算公式為:

TH1 = TL1 = 256 - 晶振值/12 /2/16 /波特率

和波特率有關(guān)的還有一個(gè)寄存器,是一個(gè)電源管理寄存器PCON,他的最高位可以把波特率提高一倍,也就是如果寫PCON |= 0x80以后,計(jì)算公式就成了:

TH1 = TL1 = 256 - 晶振值/12 /16 /波特率

公式中數(shù)字的含義這里解釋一下,256是8位定時(shí)器的溢出值,也就是TL1的溢出值,晶振值在我們的開發(fā)板上就是11059200,12是說1個(gè)機(jī)器周期等于12個(gè)時(shí)鐘周期,值得關(guān)注的是這個(gè)16,我們來重點(diǎn)說明。在IO口模擬串口通信接收數(shù)據(jù)的時(shí)候,采集的是這一位數(shù)據(jù)的中間位置,而實(shí)際上串口模塊比我們模擬的要復(fù)雜和精確一些。他采取的方式是把一位信號采集16次,其中第7、8、9次取出來,這三次中其中兩次如果是高電平,那么就認(rèn)定這一位數(shù)據(jù)是1,如果兩次是低電平,那么就認(rèn)定這一位是0,這樣一旦受到意外干擾讀錯(cuò)一次數(shù)據(jù),也依然可以保證最終數(shù)據(jù)的正確性。

串口通信的發(fā)送和接收電路在物理上有2個(gè)名字相同的SBUF寄存器,它們的地址也都是0x99,但是一個(gè)用來做發(fā)送緩沖,一個(gè)用來做接收緩沖。意思就是說,有2個(gè)房間,兩個(gè)房間的門牌號是一樣的,其中一個(gè)只出人不進(jìn)人,另外一個(gè)只進(jìn)人不出人,這樣的話,我們就可以實(shí)現(xiàn)UART的全雙工通信,相互之間不會產(chǎn)生干擾。但是在邏輯上呢,我們每次只操作SBUF,單片機(jī)會自動(dòng)根據(jù)對它執(zhí)行的是“讀”還是“寫”操作來選擇是接收SBUF還是發(fā)送SBUF,后邊通過程序,我們就會徹底了解這個(gè)問題。

UART串口程序:

一般情況下,我們編寫串口通信程序的基本步驟如下所示:

1、配置串口為模式1。

2、配置定時(shí)器T1為模式2,即自動(dòng)重裝模式。

3、根據(jù)波特率計(jì)算TH1和TL1的初值,如果有需要可以使用PCON進(jìn)行波特率加倍。

4、打開定時(shí)器控制寄存器TR1,讓定時(shí)器跑起來。

這里還要特別注意一下,就是在使用T1做波特率發(fā)生器的時(shí)候,千萬不要再使能T1的中斷了。

我們先來看一下由IO口模擬串口通信直接改為使用硬件UART模塊時(shí)的程序代碼,看看程序是不是簡單了很多,因?yàn)榇蟛糠值墓ぷ饔布K都替我們做了。程序功能和IO口模擬的是完全一樣的。

通信實(shí)例與ASCLL碼

先拋開我們使用的漢字不談,那么我們常用的字符就包含了0~9的數(shù)字、A~Z/a~z的字母、還有各種標(biāo)點(diǎn)符號等。那么在單片機(jī)系統(tǒng)里面我們怎么來表示它們呢?ASCII碼(AmericanStandardCodeforInformationInterchange,即美國信息互換標(biāo)準(zhǔn)代碼)可以完成這個(gè)使命:我們知道,在單片機(jī)中一個(gè)字節(jié)的數(shù)據(jù)可以有0~255共256個(gè)值,我們?nèi)∑渲械?~127共128個(gè)值賦予了它另外一層涵義

我們用字符格式發(fā)送一個(gè)小寫的a,返回一個(gè)十六進(jìn)制的0x61,數(shù)碼管上顯示的也是61,ASCII碼表里字符a對應(yīng)十進(jìn)制是97,等于十六進(jìn)制的0x61;我們再用字符格式發(fā)送一個(gè)數(shù)字1,返回一個(gè)十六進(jìn)制的0x31,數(shù)碼管上顯示的也是31,ASCII表里字符1對應(yīng)的十進(jìn)制是49,等于十六進(jìn)制的0x31。這下大家就該清楚了:所謂的十六進(jìn)制發(fā)送和十六進(jìn)制接收,都是按字節(jié)數(shù)據(jù)的真實(shí)值進(jìn)行的;而字符格式發(fā)送和字符格式接收,是按ASCII碼表中字符形式進(jìn)行的,但它實(shí)際上最終傳輸?shù)倪€是一個(gè)字節(jié)數(shù)據(jù)。這個(gè)表格,當(dāng)然不需要大家去記住,理解它,用的時(shí)候過來查就行了。

51單片機(jī)串口通信實(shí)例(字符串接收和發(fā)送)

#include《reg52.h》

//------------------串口通信協(xié)議-----------------//

/*

客戶端數(shù)據(jù)包格式解釋(長度恒為15):

例如:A01_fmq_01Off___#

A--------數(shù)據(jù)包的開始標(biāo)記(可以為A到Z,意味著數(shù)據(jù)包可以有26種)

01-----設(shè)備代號

fmq_01Off___--------指令(長度恒為10),指令的前4個(gè)人字符是指令頭部,指令的后6個(gè)字符是指令尾部

#---------數(shù)據(jù)包的結(jié)束標(biāo)記

服務(wù)器端數(shù)據(jù)包格式解釋(長度恒為15):

例如:A02_SenT010250#

A--------數(shù)據(jù)包的開始標(biāo)記(可以為A到Z,意味著數(shù)據(jù)包可以有26種)

02-----設(shè)備代號

SenT010250--------指令(長度恒為10),指令的前4個(gè)人字符是指令頭部,指令的后6個(gè)字符是指令尾部

#---------數(shù)據(jù)包的結(jié)束標(biāo)記

*/

char buf_string[16]; //定義數(shù)據(jù)包長度為15個(gè)字符

#define deviceID_1Bit ‘0’ //用于串口通信時(shí),定義本地設(shè)備ID的第1位

#define deviceID_2Bit ‘2’ //用于串口通信時(shí),定義本地設(shè)備ID的第2位

#define datapackage_headflag ‘A’ //用于串口通信時(shí),定義數(shù)據(jù)包頭部的驗(yàn)證標(biāo)記

char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,‘_’,‘S’,‘e’,‘n’,‘T’,‘X’,‘X’,‘X’,‘X’,‘X’,‘X’,‘#’};

char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,‘_’,‘B’,‘e’,‘a(chǎn)’,‘t’,‘X’,‘X’,‘X’,‘X’,‘X’,‘X’,‘#’};

//----------------------------------------------//

/*******************************

串口通信

MCU:89C52RC 11.0592MHz

//11.0592MHz 0xd0 1200bps

//12MHz 0xcc 1200bps

//11.0592MHz 0xfa 9600bps

//0xf4 11.0592MHz 0xf3 12MHz 4800bps

//均在SMOD=1的情況下(波特率倍增模式)

*******************************/

//串口發(fā)送函數(shù)

void PutString(unsigned char *TXStr)

{

ES=0;

while(*TXStr!=0)

{

SBUF=*TXStr;

while(TI==0);

TI=0;

TXStr++;

}

ES=1;

}

//串口接收函數(shù)

bit ReceiveString()

{

char * RecStr=buf_string;

char num=0;

unsigned char count=0;

loop:

*RecStr=SBUF;

count=0;

RI=0;

if(num《14) //數(shù)據(jù)包長度為15個(gè)字符,嘗試連續(xù)接收15個(gè)字符

{

num++;

RecStr++;

while(!RI)

{

count++;

if(count》130)return 0; //接收數(shù)據(jù)等待延遲,等待時(shí)間太久會導(dǎo)致CPU運(yùn)算閑置,太短會出現(xiàn)“數(shù)據(jù)包被分割”,默認(rèn)count=130

}

goto loop;

}

return 1;

}

//定時(shí)器1用作波特率發(fā)生器

void Init_USART()

{

SCON=0x50; //串口方式1,使能接收

TMOD|=0x20; //定時(shí)器1工作方式2(8位自動(dòng)重裝初值)

TMOD&=~0x10;

TH1=0xfa; //9600bps

TL1=0xfa;

PCON|=0x80; //SMOD=1

TR1=1;

TI=0;

RI=0;

//PS=1; //提高串口中斷優(yōu)先級

ES=1; //開啟串口中斷使能

}

//比較指令頭部

bit CompareCMD_head(char CMD_head[])

{

unsigned char CharNum;

for(CharNum=0;CharNum《4;CharNum++) //指令長度為10個(gè)字符

{

if(?。╞uf_string[CharNum+4]==CMD_head[CharNum]))

{

return 0; //指令頭部匹配失敗

}

}

return 1; //指令頭部匹配成功

}

//比較指令尾部(start:從哪里開始比較,quality:比較多少個(gè)字符,CMD_tail[]:要比較的字符串)

bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[])

{

unsigned char CharNum;

for(CharNum=0;CharNum《quality;CharNum++)

{

if(?。╞uf_string[start+CharNum]==CMD_tail[CharNum]))

{

return 0;

}

}

return 1;

}

bit Deal_UART_RecData() //處理串口接收數(shù)據(jù)包函數(shù)(成功處理數(shù)據(jù)包則返回1,否則返回0)

{

//PutString(buf_string);

if(buf_string[0]==datapackage_headflag&&buf_string[14]==‘#’) //進(jìn)行數(shù)據(jù)包頭尾標(biāo)記驗(yàn)證

{

switch(buf_string[1]) //識別發(fā)送者設(shè)備ID的第1位數(shù)字

{

case ‘0’:

switch(buf_string[2]) //識別發(fā)送者設(shè)備ID的第2位數(shù)字

{

case ‘3’:

if(CompareCMD_head(“Ligt”)) //判斷指令頭部是否為“Ligt”

{

//下面是指令尾部分析

switch(buf_string[8])

{

case ‘0’:

switch(buf_string[9])

{

case ‘0’:

return 0;

case ‘1’:

if(CompareCMD_tail(10,3,“Off”)) //A03_Ligt01Off_#

{

//要執(zhí)行的代碼

return 1;

}

if(CompareCMD_tail(10,3,“On_”))

{

return 1;

}

return 0;

default:

return 0;

}

case ‘1’:

default:

return 0;

}

}

if(CompareCMD_head(“SenT”))

{

}

if(CompareCMD_head(“jdq_”))

{

}

if(CompareCMD_head(“Try!”))

{

}

return 0;

default:

return 0;

}

default:

return 0;

}

}

return 0;

}

/************************

中斷函數(shù)

************************/

//串口中斷服務(wù)函數(shù)-----------

void USART() interrupt 4 //標(biāo)志位TI和RI需要手動(dòng)復(fù)位,TI和RI置位共用一個(gè)中斷入口

{

if(ReceiveString())

{

//數(shù)據(jù)包長度正確則執(zhí)行以下代碼

Deal_UART_RecData();

}

else

{

//數(shù)據(jù)包長度錯(cuò)誤則執(zhí)行以下代碼

//LED1=~LED1;

}

RI=0; //接收并處理一次數(shù)據(jù)后把接收中斷標(biāo)志清除一下,拒絕響應(yīng)在中斷接收忙的時(shí)候發(fā)來的請求

}

/***************************

主函數(shù)

***************************/

void main()

{

EA=1;

Init_USART();

while(1)

{

//PutString(buf_string);//空格20H,回車0DH

}

}

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6035

    文章

    44554

    瀏覽量

    634614
  • uart
    +關(guān)注

    關(guān)注

    22

    文章

    1235

    瀏覽量

    101353
  • 串口通信
    +關(guān)注

    關(guān)注

    34

    文章

    1624

    瀏覽量

    55507

原文標(biāo)題:深入理解51單片機(jī)串口通信及通信實(shí)例

文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    幾種IO模擬UART的方案

    好了,今天為大家?guī)韼追NIO模擬串口"硬核"操作,相信大家對類似于串口這樣的電平類通信會有新的
    的頭像 發(fā)表于 07-30 10:34 ?5725次閱讀

    IO模擬串口UART

    IO模擬串口UART 本文介紹GPIO模擬UART的算法和實(shí)現(xiàn)
    發(fā)表于 04-03 14:11 ?86次下載

    niosii的UART串口通信

    niosii的UART串口通信niosii的UART串口通信。
    發(fā)表于 04-06 17:03 ?1次下載

    深入理解51單片機(jī)串口通信通信實(shí)例

    全文首先闡述了串口通信的原理及RS232相關(guān)概述,其次介紹了USB轉(zhuǎn)串口通信IO
    發(fā)表于 04-19 16:52 ?2.7w次閱讀
    深入理解51單片機(jī)<b class='flag-5'>串口</b><b class='flag-5'>通信</b>及<b class='flag-5'>通信</b>實(shí)例

    串口通信的原理及USB轉(zhuǎn)串口通信

    IO模擬串口通信,讓大家了解了串口通信的本質(zhì),但是
    的頭像 發(fā)表于 05-07 15:54 ?9.7w次閱讀
    <b class='flag-5'>串口</b><b class='flag-5'>通信</b>的原理及USB轉(zhuǎn)<b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    幾種IO模擬串口"硬核"操作

    1、聊一聊 好了,今天為大家?guī)韼追NIO模擬串口硬核操作,相信大家對類似于串口這樣的電平類通信
    的頭像 發(fā)表于 10-13 17:44 ?1.4w次閱讀
    幾種<b class='flag-5'>IO</b><b class='flag-5'>口</b><b class='flag-5'>模擬</b><b class='flag-5'>串口</b>"硬核"操作

    幾種IO模擬串口&quot;硬核&quot;操作

    1、聊一聊 好了,今天為大家?guī)韼追NIO模擬串口"硬核"操作,相信大家對類似于串口這樣的電平類通信
    的頭像 發(fā)表于 02-10 11:51 ?4865次閱讀
    幾種<b class='flag-5'>IO</b><b class='flag-5'>口</b><b class='flag-5'>模擬</b><b class='flag-5'>串口</b>&quot;硬核&quot;操作

    【妙招】一份 " IO模擬串口 " 獨(dú)門秘籍

    1、聊一聊 好了,今天為大家?guī)韼追NIO模擬串口"硬核"操作,相信大家對類似于串口這樣的電平類通信
    發(fā)表于 01-30 06:35 ?35次下載
    【妙招】一份 " <b class='flag-5'>IO</b><b class='flag-5'>口</b><b class='flag-5'>模擬</b><b class='flag-5'>串口</b> " 獨(dú)門秘籍

    幾種IO模擬串口“硬核”操作

    對類似于串口這樣的電平類通信會有新的認(rèn)識。 2、IO模擬串口需求 "IO
    的頭像 發(fā)表于 04-04 11:28 ?2310次閱讀
    幾種<b class='flag-5'>IO</b><b class='flag-5'>口</b><b class='flag-5'>模擬</b><b class='flag-5'>串口</b>“硬核”操作

    C51的UART 串口通信

    C51的UART 串口通信
    發(fā)表于 11-29 12:21 ?11次下載
    C51的<b class='flag-5'>UART</b> <b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    STM8S103系列IO模擬串口通信(實(shí)現(xiàn)真正串口

    STM8s103f3p3單片機(jī)只有一個(gè)串口,有時(shí)候在實(shí)際項(xiàng)目中,我們需要用到多個(gè)串口來實(shí)現(xiàn)項(xiàng)目要求,此時(shí),我們可以通過IO模擬
    發(fā)表于 12-27 18:51 ?27次下載
    STM8S103系列<b class='flag-5'>IO</b><b class='flag-5'>口</b><b class='flag-5'>模擬</b><b class='flag-5'>串口</b><b class='flag-5'>通信</b>(實(shí)現(xiàn)真正<b class='flag-5'>串口</b>)

    單片機(jī)IO模擬UART串口通信

    為了讓大家充分理解 UART 串口通信的原理,我們先把 P3.0 和 P3.1 當(dāng)做 IO 來進(jìn)行模擬
    發(fā)表于 02-09 10:25 ?25次下載
    單片機(jī)<b class='flag-5'>IO</b><b class='flag-5'>口</b><b class='flag-5'>模擬</b><b class='flag-5'>UART</b><b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    STM32模擬串口(UART)使用

    首先我們先添加相應(yīng)的頭文件。既然我們要進(jìn)行對串口模擬,因此我們要先了解uart相關(guān)的通信協(xié)議。由于UART
    的頭像 發(fā)表于 03-22 15:56 ?6434次閱讀

    一份“IO模擬串口”獨(dú)門秘籍

    今天為大家?guī)韼追NIO模擬串口"硬核"操作,相信大家對類似于串口這樣的電平類通信會有新的認(rèn)識。
    的頭像 發(fā)表于 05-14 09:55 ?4015次閱讀
    一份“<b class='flag-5'>IO</b><b class='flag-5'>口</b><b class='flag-5'>模擬</b><b class='flag-5'>串口</b>”獨(dú)門秘籍

    UART串口通信協(xié)議是什么?

    UART (Universal Asynchronous Receiver/Transmitter) 是一種通信接口協(xié)議,用于實(shí)現(xiàn)串口通信。它是一種簡單的、可靠的、廣泛應(yīng)用的
    的頭像 發(fā)表于 03-19 17:26 ?1365次閱讀
    RM新时代网站-首页