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