詳細(xì)解析串口通信的原理及USB轉(zhuǎn)串口通信
發(fā)布時(shí)間:2018-05-07 來(lái)源:傳感器技術(shù) 責(zé)任編輯:lina
【導(dǎo)讀】串口通信(SerialCommunicaTIons)的概念非常簡(jiǎn)單,串口按位(bit)發(fā)送和接收字節(jié)。盡管比按字節(jié)(byte)的并行通信慢,但是串口可以在使用一根線發(fā)送數(shù)據(jù)的同時(shí)用另一根線接收數(shù)據(jù)。它很簡(jiǎn)單并且能夠?qū)崿F(xiàn)遠(yuǎn)距離通信。
串口通信的原理
串口通信(SerialCommunicaTIons)的概念非常簡(jiǎn)單,串口按位(bit)發(fā)送和接收字節(jié)。盡管比按字節(jié)(byte)的并行通信慢,但是串口可以在使用一根線發(fā)送數(shù)據(jù)的同時(shí)用另一根線接收數(shù)據(jù)。它很簡(jiǎn)單并且能夠?qū)崿F(xiàn)遠(yuǎn)距離通信。比如IEEE488定義并行通行狀態(tài)時(shí),規(guī)定設(shè)備線總長(zhǎng)不得超過(guò)20米,并且任意兩個(gè)設(shè)備間的長(zhǎng)度不得超過(guò)2米;而對(duì)于串口而言,長(zhǎng)度可達(dá)1200米。典型地,串口用于ASCII碼字符的傳輸。通信使用3根線完成,分別是地線、發(fā)送、接收。由于串口通信是異步的,端口能夠在一根線上發(fā)送數(shù)據(jù)同時(shí)在另一根線上接收數(shù)據(jù)。其他線用于握手,但不是必須的。串口通信最重要的參數(shù)是波特率、數(shù)據(jù)位、停止位和奇偶校驗(yàn)。對(duì)于兩個(gè)進(jìn)行通信的端口,這些參數(shù)必須匹配。
a,波特率:這是一個(gè)衡量符號(hào)傳輸速率的參數(shù)。指的是信號(hào)被調(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ù)往往不會(huì)是8位的,標(biāo)準(zhǔn)的值是6、7和8位。如何設(shè)置取決于你想傳送的信息。比如,標(biāo)準(zhǔn)的ASCII碼是0~127(7位)。擴(kuò)展的ASCII碼是0~255(8位)。如果數(shù)據(jù)使用簡(jiǎn)單的文本(標(biāo)準(zhǔn)ASCII碼),那么每個(gè)數(shù)據(jù)包使用7位數(shù)據(jù)。每個(gè)包是指一個(gè)字節(jié),包括開(kāi)始/停止位,數(shù)據(jù)位和奇偶校驗(yàn)位。由于實(shí)際數(shù)據(jù)位取決于通信協(xié)議的選取,術(shù)語(yǔ)“包”指任何通信的情況。
c,停止位:用于表示單個(gè)包的最后一位。典型的值為1,1.5和2位。由于數(shù)據(jù)是在傳輸線上定時(shí)的,并且每一個(gè)設(shè)備有其自己的時(shí)鐘,很可能在通信中兩臺(tái)設(shè)備間出現(xiàn)了小小的不同步。因此停止位不僅僅是表示傳輸?shù)慕Y(jié)束,并且提供計(jì)算機(jī)校正時(shí)鐘同步的機(jī)會(huì)。適用于停止位的位數(shù)越多,不同時(shí)鐘同步的容忍程度越大,但是數(shù)據(jù)傳輸率同時(shí)也越慢。
d,奇偶校驗(yàn)位:在串口通信中一種簡(jiǎn)單的檢錯(cuò)方式。有四種檢錯(cuò)方式:偶、奇、高和低。當(dāng)然沒(méi)有校驗(yàn)位也是可以的。對(duì)于偶和奇校驗(yàn)的情況,串口會(huì)設(shè)置校驗(yàn)位(數(shù)據(jù)位后面的一位),用一個(gè)值確保傳輸?shù)臄?shù)據(jù)有偶個(gè)或者奇?zhèn)€邏輯高位。例如,如果數(shù)據(jù)是011,那么對(duì)于偶校驗(yàn),校驗(yàn)位為0,保證邏輯高的位數(shù)是偶數(shù)個(gè)。如果是奇校驗(yàn),校驗(yàn)位為1,這樣就有3個(gè)邏輯高位。高位和低位不真正的檢查數(shù)據(jù),簡(jiǎn)單置位邏輯高或者邏輯低校驗(yàn)。這樣使得接收設(shè)備能夠知道一個(gè)位的狀態(tài),有機(jī)會(huì)判斷是否有噪聲干擾了通信或者是否傳輸和接收數(shù)據(jù)是否不同步。
RS232概述
在我們電腦上,一般都會(huì)有一個(gè)9針的串行接口,這個(gè)串行接口叫做RS232接口,它和UART通信有關(guān)聯(lián),但是由于現(xiàn)在筆記本電腦不帶9針串口,所以和單片機(jī)通信越來(lái)越趨于使用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、載波檢測(cè)DCD;2、接收數(shù)據(jù)RXD;3、發(fā)送數(shù)據(jù)TXD;4、數(shù)據(jù)終端準(zhǔn)備好DTR;5、信號(hào)地線SG;6、數(shù)據(jù)準(zhǔn)備好DSR;7、請(qǐng)求發(fā)送RTS;8、清除發(fā)送CTS;9、振鈴提示RI。我們要讓這個(gè)串口和我們單片機(jī)進(jìn)行通信,我們只需要關(guān)心其中的2腳RXD、3腳TXD和5腳GND即可
雖然這三個(gè)引腳的名字和我們單片機(jī)上的串口名字一樣,但是卻不能直接和單片機(jī)對(duì)連通信,這是為什么呢?隨著我們了解的內(nèi)容越來(lái)越多,我們得慢慢知道,不是所有的電路都是5V代表高電平而0V代表低電平的。對(duì)于RS232標(biāo)準(zhǔn)來(lái)說(shuō),它是個(gè)反邏輯,也叫做負(fù)邏輯。為何叫負(fù)邏輯?它的TXD和RXD的電壓,-3V~-15V電壓代表是1,+3~+15V電壓代表是0。低電平代表的是1,而高電平代表的是0,所以稱(chēng)之為負(fù)邏輯。因此電腦的9針RS232串口是不能和單片機(jī)直接連接的,需要用一個(gè)電平轉(zhuǎn)換芯片MAX232來(lái)完成
這個(gè)芯片就可以實(shí)現(xiàn)把標(biāo)準(zhǔn)RS232串口電平轉(zhuǎn)換成我們單片機(jī)能夠識(shí)別和承受的UART0V/5V電平。從這里大家似乎慢慢有點(diǎn)明白了,其實(shí)RS232串口和UART串口,它們的協(xié)議類(lèi)型是一樣的,只是電平標(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)沒(méi)有串口這個(gè)東西了,那我們要實(shí)現(xiàn)單片機(jī)和電腦之間的通信該怎么辦呢?
們只需要在電路上添加一個(gè)USB轉(zhuǎn)串口芯片,就可以成功實(shí)現(xiàn)USB通信協(xié)議和標(biāo)準(zhǔn)UART串行通信協(xié)議的轉(zhuǎn)換,在我們的開(kāi)發(fā)板上,我們使用的是CH340T這個(gè)芯片
我們需要用跳線帽把中間和下邊的針短接在一起。右側(cè)的CH340T這個(gè)電路很簡(jiǎn)單,把電源、晶振接好后,6腳和7腳的DP和DM分別接USB口的2個(gè)數(shù)據(jù)引腳上去,3腳和4腳通過(guò)跳線接到了我們單片機(jī)的TXD和RXD上去。
CH340T的電路里3腳位置加了個(gè)4148的二極管,是一個(gè)小技巧。因?yàn)镾TC89C52這個(gè)單片機(jī)下載程序時(shí)需要冷啟動(dòng),就是先點(diǎn)下載后上電,上電瞬間單片機(jī)會(huì)先檢測(cè)需要不需要下載程序。雖然單片機(jī)的VCC是由開(kāi)關(guān)來(lái)控制,但是由于CH340T的3腳是輸出引腳,如果沒(méi)有此二極管,開(kāi)關(guān)后級(jí)單片機(jī)在斷電的情況下,CH340T的3腳和單片機(jī)的P3.0(即RXD)引腳連在一起,有電流會(huì)通過(guò)這個(gè)引腳流入后級(jí)電路并且給后級(jí)的電容充電,造成后級(jí)有一定幅度的電壓,這個(gè)電壓值雖然只有兩三伏左右,但是可能會(huì)影響到正常的冷啟動(dòng)。加了二極管后,一方面不影響通信,另外一個(gè)方面還可以消除這種不良影響。這個(gè)地方可以暫時(shí)作為了解,大家如果自己做這類(lèi)電路,可以參考一下。
IO口模擬UART串口通信
UART串口波特率,常用的值是300、600、1200、2400、4800、9600、14400、19200、28800、38400、57600、115200等速率。IO口模擬UART串行通信程序是一個(gè)簡(jiǎn)單的演示程序,我們使用串口調(diào)試助手下發(fā)一個(gè)數(shù)據(jù),數(shù)據(jù)加1后,再自動(dòng)返回。
串口調(diào)試助手,這里我們直接使用STC-ISP軟件自帶的串口調(diào)試助手,先把串口調(diào)試助手的使用給大家說(shuō)一下,如圖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)行一下解釋?zhuān)蠹铱梢赃吙次业慕忉屵吙闯绦颍训讓釉硐葟氐着?/div>
變量定義部分就不用說(shuō)了,直接看main主函數(shù)。首先是對(duì)通信的波特率的設(shè)定,在這里我們配置的波特率是9600,那么串口調(diào)試助手也得是9600。配置波特率的時(shí)候,我們用的是定時(shí)器T0的模式2。模式2中,不再是TH0代表高8位,TL0代表低8位了,而只有TL0在進(jìn)行計(jì)數(shù),當(dāng)TL0溢出后,不僅僅會(huì)讓TF0變1,而且還會(huì)將TH0中的內(nèi)容重新自動(dòng)裝到TL0中。這樣有一個(gè)好處,就是我們可以把想要的定時(shí)器初值提前存在TH0中,當(dāng)TL0溢出后,TH0自動(dòng)把初值就重新送入TL0了,全自動(dòng)的,不需要程序中再給TL0重新賦值了,配置方式很簡(jiǎn)單,大家可以自己看下程序并且計(jì)算一下初值。
波特率設(shè)置好以后,打開(kāi)中斷,然后等待接收串口調(diào)試助手下發(fā)的數(shù)據(jù)。接收數(shù)據(jù)的時(shí)候,首先要進(jìn)行低電平檢測(cè)while(PIN_RXD),若沒(méi)有低電平則說(shuō)明沒(méi)有數(shù)據(jù),一旦檢測(cè)到低電平,就進(jìn)入啟動(dòng)接收函數(shù)StartRXD()。接收函數(shù)最開(kāi)始啟動(dòng)半個(gè)波特率周期,初學(xué)可能這里不是很明白。大家回頭看一下我們的圖11-2里邊的串口數(shù)據(jù)示意圖,如果在數(shù)據(jù)位電平變化的時(shí)候去讀取,因?yàn)闀r(shí)序上的誤差以及信號(hào)穩(wěn)定性的問(wèn)題很容易讀錯(cuò)數(shù)據(jù),所以我們希望在信號(hào)最穩(wěn)定的時(shí)候去讀數(shù)據(jù)。除了信號(hào)變化的那個(gè)沿的位置外,其它位置都很穩(wěn)定,那么我們現(xiàn)在就約定在信號(hào)中間位置去讀取電平狀態(tài),這樣能夠保證我們讀的一定是正確的。
一旦讀到了起始信號(hào),我們就把當(dāng)前狀態(tài)設(shè)定成接收狀態(tài),并且打開(kāi)定時(shí)器中斷,第一次是半個(gè)周期進(jìn)入中斷后,對(duì)起始位進(jìn)行二次判斷一下,確認(rèn)一下起始位是低電平,而不是一個(gè)干擾信號(hào)。以后每經(jīng)過(guò)1/9600秒進(jìn)入一次中斷,并且把這個(gè)引腳的狀態(tài)讀到RxdBuf里邊。等待接收完畢之后,我們?cè)侔堰@個(gè)RxdBuf加1,再通過(guò)TXD引腳發(fā)送出去,同樣需要先發(fā)一位起始位,然后發(fā)8個(gè)數(shù)據(jù)位,再發(fā)結(jié)束位,發(fā)送完畢后,程序運(yùn)行到while(PIN_RXD),等待第二輪信號(hào)接收的開(kāi)始。
uart模塊介紹
IO口模擬串口通信,讓大家了解了串口通信的本質(zhì),但是我們的單片機(jī)程序卻需要不停的檢測(cè)掃描單片機(jī)IO口收到的數(shù)據(jù),大量占用了單片機(jī)的運(yùn)行時(shí)間。這時(shí)候就會(huì)有聰明人想了,其實(shí)我們并不是很關(guān)心通信的過(guò)程,我們只需要一個(gè)通信的結(jié)果,最終得到接收到的數(shù)據(jù)就行了。這樣我們可以在單片機(jī)內(nèi)部做一個(gè)硬件模塊,讓它自動(dòng)接收數(shù)據(jù),接收完了,通知我們一下就可以了,我們的51單片機(jī)內(nèi)部就存在這樣一個(gè)UART模塊,要正確使用它,當(dāng)然還得先把對(duì)應(yīng)的特殊功能寄存器配置好。
51單片機(jī)的UART串口的結(jié)構(gòu)由串行口控制寄存器SCON、發(fā)送和接收電路三部分構(gòu)成,先來(lái)了解一下串口控制寄存器SCON。
SCON串行控制器的位分配(地址:0x98)
位:符號(hào):復(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,必須通過(guò)軟件清零
1位TI:發(fā)送中斷標(biāo)志位,當(dāng)發(fā)送電路發(fā)送到停止位的中間位置時(shí),TI由硬件置1,必須通過(guò)軟件清零。
2位RB8:模式2和3中接收到的第9位數(shù)據(jù)(很少用),模式1用來(lái)接收停止位。
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,其它模式從略。
對(duì)于串口的四種模式,模式1是最常用的,就是我們前邊提到的1位起始位,8位數(shù)據(jù)位和1位停止位。下面我們就詳細(xì)介紹模式1的工作細(xì)節(jié)和使用方法,至于其它3種模式與此也是大同小異,真正遇到需要使用的時(shí)候大家再去查閱相關(guān)資料就行了。
在我們使用IO口模擬串口通信的時(shí)候,串口的波特率是使用定時(shí)器T0的中斷體現(xiàn)出來(lái)的。在硬件串口模塊中,有一個(gè)專(zhuān)門(mén)的波特率發(fā)生器用來(lái)控制發(fā)送和接收數(shù)據(jù)的速度。對(duì)于STC89C52單片機(jī)來(lái)講,這個(gè)波特率發(fā)生器只能由定時(shí)器T1或定時(shí)器T2產(chǎn)生,而不能由定時(shí)器T0產(chǎn)生,這和我們模擬的通信是完全不同的概念。
如果用定時(shí)器2,需要配置額外的寄存器,默認(rèn)是使用定時(shí)器1的,我們本章內(nèi)容主要就使用定時(shí)器T1作為波特率發(fā)生器來(lái)講解,方式1下的波特率發(fā)生器必須使用定時(shí)器T1的模式2,也就是自動(dòng)重裝載模式,定時(shí)器的重載值計(jì)算公式為:
TH1 = TL1 = 256 - 晶振值/12 /2/16 /波特率
和波特率有關(guān)的還有一個(gè)寄存器,是一個(gè)電源管理寄存器PCON,他的最高位可以把波特率提高一倍,也就是如果寫(xiě)PCON |= 0x80以后,計(jì)算公式就成了:
TH1 = TL1 = 256 - 晶振值/12 /16 /波特率
公式中數(shù)字的含義這里解釋一下,256是8位定時(shí)器的溢出值,也就是TL1的溢出值,晶振值在我們的開(kāi)發(fā)板上就是11059200,12是說(shuō)1個(gè)機(jī)器周期等于12個(gè)時(shí)鐘周期,值得關(guān)注的是這個(gè)16,我們來(lái)重點(diǎn)說(shuō)明。在IO口模擬串口通信接收數(shù)據(jù)的時(shí)候,采集的是這一位數(shù)據(jù)的中間位置,而實(shí)際上串口模塊比我們模擬的要復(fù)雜和精確一些。他采取的方式是把一位信號(hào)采集16次,其中第7、8、9次取出來(lái),這三次中其中兩次如果是高電平,那么就認(rèn)定這一位數(shù)據(jù)是1,如果兩次是低電平,那么就認(rèn)定這一位是0,這樣一旦受到意外干擾讀錯(cuò)一次數(shù)據(jù),也依然可以保證最終數(shù)據(jù)的正確性。
串口通信的發(fā)送和接收電路在物理上有2個(gè)名字相同的SBUF寄存器,它們的地址也都是0x99,但是一個(gè)用來(lái)做發(fā)送緩沖,一個(gè)用來(lái)做接收緩沖。意思就是說(shuō),有2個(gè)房間,兩個(gè)房間的門(mén)牌號(hào)是一樣的,其中一個(gè)只出人不進(jìn)人,另外一個(gè)只進(jìn)人不出人,這樣的話,我們就可以實(shí)現(xiàn)UART的全雙工通信,相互之間不會(huì)產(chǎn)生干擾。但是在邏輯上呢,我們每次只操作SBUF,單片機(jī)會(huì)自動(dòng)根據(jù)對(duì)它執(zhí)行的是“讀”還是“寫(xiě)”操作來(lái)選擇是接收SBUF還是發(fā)送SBUF,后邊通過(guò)程序,我們就會(huì)徹底了解這個(gè)問(wèn)題。
UART串口程序:
一般情況下,我們編寫(xiě)串口通信程序的基本步驟如下所示:
1、配置串口為模式1。
2、配置定時(shí)器T1為模式2,即自動(dòng)重裝模式。
3、根據(jù)波特率計(jì)算TH1和TL1的初值,如果有需要可以使用PCON進(jìn)行波特率加倍。
4、打開(kāi)定時(shí)器控制寄存器TR1,讓定時(shí)器跑起來(lái)。
這里還要特別注意一下,就是在使用T1做波特率發(fā)生器的時(shí)候,千萬(wàn)不要再使能T1的中斷了。
我們先來(lái)看一下由IO口模擬串口通信直接改為使用硬件UART模塊時(shí)的程序代碼,看看程序是不是簡(jiǎn)單了很多,因?yàn)榇蟛糠值墓ぷ饔布K都替我們做了。程序功能和IO口模擬的是完全一樣的。
通信實(shí)例與ASCLL碼
先拋開(kāi)我們使用的漢字不談,那么我們常用的字符就包含了0~9的數(shù)字、A~Z/a~z的字母、還有各種標(biāo)點(diǎn)符號(hào)等。那么在單片機(jī)系統(tǒng)里面我們?cè)趺磥?lái)表示它們呢?ASCII碼(AmericanStandardCodeforInformationInterchange,即美國(guó)信息互換標(biāo)準(zhǔn)代碼)可以完成這個(gè)使命:我們知道,在單片機(jī)中一個(gè)字節(jié)的數(shù)據(jù)可以有0~255共256個(gè)值,我們?nèi)∑渲械?~127共128個(gè)值賦予了它另外一層涵義
我們用字符格式發(fā)送一個(gè)小寫(xiě)的a,返回一個(gè)十六進(jìn)制的0x61,數(shù)碼管上顯示的也是61,ASCII碼表里字符a對(duì)應(yīng)十進(jìn)制是97,等于十六進(jìn)制的0x61;我們?cè)儆米址袷桨l(fā)送一個(gè)數(shù)字1,返回一個(gè)十六進(jìn)制的0x31,數(shù)碼管上顯示的也是31,ASCII表里字符1對(duì)應(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í)候過(guò)來(lái)查就行了。
51單片機(jī)串口通信實(shí)例(字符串接收和發(fā)送)
#include《reg52.h》
//------------------串口通信協(xié)議-----------------//
/*
客戶(hù)端數(shù)據(jù)包格式解釋?zhuān)ㄩL(zhǎng)度恒為15):
例如:A01_fmq_01Off___#
A--------數(shù)據(jù)包的開(kāi)始標(biāo)記(可以為A到Z,意味著數(shù)據(jù)包可以有26種)
01-----設(shè)備代號(hào)
fmq_01Off___--------指令(長(zhǎng)度恒為10),指令的前4個(gè)人字符是指令頭部,指令的后6個(gè)字符是指令尾部
#---------數(shù)據(jù)包的結(jié)束標(biāo)記
服務(wù)器端數(shù)據(jù)包格式解釋?zhuān)ㄩL(zhǎng)度恒為15):
例如:A02_SenT010250#
A--------數(shù)據(jù)包的開(kāi)始標(biāo)記(可以為A到Z,意味著數(shù)據(jù)包可以有26種)
02-----設(shè)備代號(hào)
SenT010250--------指令(長(zhǎng)度恒為10),指令的前4個(gè)人字符是指令頭部,指令的后6個(gè)字符是指令尾部
#---------數(shù)據(jù)包的結(jié)束標(biāo)記
*/
char buf_string[16]; //定義數(shù)據(jù)包長(zhǎng)度為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’,‘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ù)包長(zhǎng)度為15個(gè)字符,嘗試連續(xù)接收15個(gè)字符
{
num++;
RecStr++;
while(!RI)
{
count++;
if(count》130)return 0; //接收數(shù)據(jù)等待延遲,等待時(shí)間太久會(huì)導(dǎo)致CPU運(yùn)算閑置,太短會(huì)出現(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)先級(jí)
ES=1; //開(kāi)啟串口中斷使能
}
//比較指令頭部
bit CompareCMD_head(char CMD_head[])
{
unsigned char CharNum;
for(CharNum=0;CharNum《4;CharNum++) //指令長(zhǎng)度為10個(gè)字符
{
if(?。╞uf_string[CharNum+4]==CMD_head[CharNum]))
{
return 0; //指令頭部匹配失敗
}
}
return 1; //指令頭部匹配成功
}
//比較指令尾部(start:從哪里開(kāi)始比較,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(!(buf_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]) //識(shí)別發(fā)送者設(shè)備ID的第1位數(shù)字
{
case ‘0’:
switch(buf_string[2]) //識(shí)別發(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ǎng)度正確則執(zhí)行以下代碼
Deal_UART_RecData();
}
else
{
//數(shù)據(jù)包長(zhǎng)度錯(cuò)誤則執(zhí)行以下代碼
//LED1=~LED1;
}
RI=0; //接收并處理一次數(shù)據(jù)后把接收中斷標(biāo)志清除一下,拒絕響應(yīng)在中斷接收忙的時(shí)候發(fā)來(lái)的請(qǐng)求
}
/***************************
主函數(shù)
***************************/
void main()
{
EA=1;
Init_USART();
while(1)
{
//PutString(buf_string);//空格20H,回車(chē)0DH
}
}
特別推薦
- 克服碳化硅制造挑戰(zhàn),助力未來(lái)電力電子應(yīng)用
- 了解交流電壓的產(chǎn)生
- 單結(jié)晶體管符號(hào)和結(jié)構(gòu)
- 英飛凌推出用于汽車(chē)應(yīng)用識(shí)別和認(rèn)證的新型指紋傳感器IC
- Vishay推出負(fù)載電壓達(dá)100 V的業(yè)內(nèi)先進(jìn)的1 Form A固態(tài)繼電器
- 康佳特推出搭載AMD 銳龍嵌入式 8000系列的COM Express緊湊型模塊
- 村田推出3225尺寸車(chē)載PoC電感器LQW32FT_8H系列
技術(shù)文章更多>>
- “扒開(kāi)”超級(jí)電容的“外衣”,看看超級(jí)電容“超級(jí)”在哪兒
- DigiKey 誠(chéng)邀各位參會(huì)者蒞臨SPS 2024?展會(huì)參觀交流,體驗(yàn)最新自動(dòng)化產(chǎn)品
- 提前圍觀第104屆中國(guó)電子展高端元器件展區(qū)
- 高性能碳化硅隔離柵極驅(qū)動(dòng)器如何選型,一文告訴您
- 貿(mào)澤電子新品推薦:2024年第三季度推出將近7000個(gè)新物料
技術(shù)白皮書(shū)下載更多>>
- 車(chē)規(guī)與基于V2X的車(chē)輛協(xié)同主動(dòng)避撞技術(shù)展望
- 數(shù)字隔離助力新能源汽車(chē)安全隔離的新挑戰(zhàn)
- 汽車(chē)模塊拋負(fù)載的解決方案
- 車(chē)用連接器的安全創(chuàng)新應(yīng)用
- Melexis Actuators Business Unit
- Position / Current Sensors - Triaxis Hall
熱門(mén)搜索
友情鏈接(QQ:317243736)
我愛(ài)方案網(wǎng) ICGOO元器件商城 創(chuàng)芯在線檢測(cè) 芯片查詢(xún) 天天IC網(wǎng) 電子產(chǎn)品世界 無(wú)線通信模塊 控制工程網(wǎng) 電子開(kāi)發(fā)網(wǎng) 電子技術(shù)應(yīng)用 與非網(wǎng) 世紀(jì)電源網(wǎng) 21ic電子技術(shù)資料下載 電源網(wǎng) 電子發(fā)燒友網(wǎng) 中電網(wǎng) 中國(guó)工業(yè)電器網(wǎng) 連接器 礦山設(shè)備網(wǎng) 工博士 智慧農(nóng)業(yè) 工業(yè)路由器 天工網(wǎng) 乾坤芯 電子元器件采購(gòu)網(wǎng) 亞馬遜KOL 聚合物鋰電池 工業(yè)自動(dòng)化設(shè)備 企業(yè)查詢(xún) 工業(yè)路由器 元器件商城 連接器 USB中文網(wǎng) 今日招標(biāo)網(wǎng) 塑料機(jī)械網(wǎng) 農(nóng)業(yè)機(jī)械 中國(guó)IT產(chǎn)經(jīng)新聞網(wǎng) 高低溫試驗(yàn)箱
?
關(guān)閉
?
關(guān)閉