單片機C51編程幾個有用的模塊
通訊模塊
串口資源做為單片機與外界通信的常用手段,通訊模塊提供了完全緩沖的串口通訊底層機制,適用于長度不大的數(shù)據(jù)包的發(fā)送及接收。如果處理關鍵數(shù)據(jù),需要用戶自己提供糾錯協(xié)議。
通訊模塊由聲明文件SComm.h及實現(xiàn)文件SComm.c組成。
初始化:調(diào)用函數(shù)InitSCommModule()來初始化通訊模塊:
voidInitSCommModule(BYTEbyTimerReload,BITbitTurbo)
參數(shù)說明:
byTimerReload:定時器1的重裝載初始值。
bitTurob:當此參數(shù)為TRUE時,串行通訊在定時器1的溢出速率基礎上加倍。為FALSE時,串行通訊速率為定時器1的溢出速率。
緩沖區(qū):模塊使用了由宏SCOMM_SENDBUFSIZE、SCOMM_RECEBUFSIZE及SCOMM_PKGBUFSIZE所指定長度的三個緩沖區(qū),分別為發(fā)送、接收及數(shù)據(jù)包(用于處理接收到的數(shù)據(jù))緩沖區(qū)(如果沒有使用異步接收功能,則不需要使用數(shù)據(jù)包緩沖區(qū))。
在缺省時,這三個宏都被定義為10,但用戶可以自已按照系統(tǒng)的RAM資源占用情況在Config.h中重定義緩沖區(qū)的大小。需要注意的是,如果緩沖的長度不夠,當發(fā)送或接收長數(shù)據(jù)包的時候可能會發(fā)生問題,關于數(shù)據(jù)緩沖區(qū)的最小值的設置可以參考下面的說明。
注意:需要盡快取出接收緩沖區(qū)中的數(shù)據(jù),否則當緩沖區(qū)滿之后,新的數(shù)據(jù)將被簡單的丟掉。
字節(jié)級服務函數(shù):在Config.h文件中定義了宏SCOMM_DriverInterface(如:#defineSCOMM_DriverInterface),則可以使用字節(jié)級服務函數(shù),即通訊模塊的底層函數(shù)。
共有兩個函數(shù)可以使用:
voidSendByte(BYTEbyData);
發(fā)送一個字節(jié),如果當前緩沖區(qū)滿,則等待。參數(shù)byData為要發(fā)送的數(shù)據(jù)。
BYTEReceByte();
接收一個字節(jié),如果當前緩沖區(qū)中沒有數(shù)據(jù),則此函數(shù)阻塞,直到接收到數(shù)據(jù)為止。接收到數(shù)據(jù)通過返回值返回。
可以通過調(diào)用IsSendBufEmpty()IsSendBufFull()IsReceBufEmpty()IsReceBufFull()宏來判斷緩沖區(qū)的空或滿,以防系統(tǒng)阻塞。
不推薦直接使用這一級的服務函數(shù),應該使用高層次上的服務函數(shù)或者在這一級服務函數(shù)的基礎上構造自己的通訊函數(shù)。
數(shù)據(jù)包級服務函數(shù):在Config.h文件中定義宏SCOMM_PackageInterface(如:#defineSCOMM_PackageInterface)則可以使用數(shù)據(jù)包級服務函數(shù)。
共有兩個函數(shù)可以使用:
voidSendPackage(BYTE*pbyData,BYTEbyLen);
發(fā)送數(shù)據(jù)包,參數(shù)pbyData為將要發(fā)送的數(shù)據(jù)包緩沖區(qū)(數(shù)組)的指針,byLen為將要發(fā)送的數(shù)據(jù)包的長度。
當沒有定義SCOMM_DriverInterface時,數(shù)據(jù)被完全緩沖。即不能夠發(fā)送長度超過發(fā)送緩沖區(qū)長度的數(shù)據(jù)包。當定義了SCOMM_DriverInterface時,采用單字節(jié)發(fā)送,這時不限制需要發(fā)送的數(shù)據(jù)的長度。
BYTERecePackage(BYTE*pbyData,BYTEbyLen);
接收數(shù)據(jù)包,參數(shù)pbyData為存放將要接收的數(shù)據(jù)的緩沖區(qū),byLen為緩沖區(qū)長度。返回值為接收到的字節(jié)數(shù),當模塊的接收緩沖區(qū)為空時,函數(shù)非阻塞,立即返回,返回值為零。
同步發(fā)送接收服務函數(shù):
比如在一個串行總線多機通訊系統(tǒng)中,主機需要定時循檢各從機的狀態(tài),往往是發(fā)一個包含從機地址及指令的數(shù)據(jù)包給從機,之后等待一定的時間,從機需要在這段時間之內(nèi)給主機一個應答,如果沒有這個應答,則認為從機工作狀態(tài)出錯,轉去進行相應的處理。在這個模型里,主機不能夠不進行等待而給另一臺從機發(fā)送指令,也不能夠不管從機在很久沒有應答的情況下繼續(xù)等待。還有一種情況,比如當使用485總線進行通信時,如果是兩條通訊線則系統(tǒng)只能工作在半雙工模式下,總線在同一時間內(nèi)只能工作在發(fā)送或接收,為了防止發(fā)送和接收相互干擾,這時的通訊常常需要使用同步發(fā)送和接收。
當在Config.h文件中定義宏SCOMM_SyncInterface后,則可以使用通訊模塊提供同步發(fā)送接收函數(shù):
voidSendPackage(BYTE*pbyData,BYTEbyLen);
發(fā)送數(shù)據(jù)包,參數(shù)pbyData為將要改善的數(shù)據(jù)包的緩沖區(qū)指針,byLen為將要發(fā)送的數(shù)據(jù)包的長度。
這個函數(shù)可以保證等待一個完整的數(shù)據(jù)包完全發(fā)送出去之后,它才返回,在這段時間內(nèi),它會阻塞運行。
BYTESyncRecePackage(BYTE*pbyBuf,BYTEbyBufLen,WORDwTimeout,BYTEbyParam);
接收數(shù)據(jù)包。返回值為接收到的數(shù)據(jù)包長度。參數(shù)pbyBuf為將要接收數(shù)據(jù)包的緩沖區(qū)的指針,byBufLen為提供的緩沖區(qū)的長度,wTimeout為通信超時值,如果在發(fā)生了由wTimeout所指定次數(shù)的時鐘中斷而還沒有接收到或沒有接收到完整的數(shù)據(jù)包時,函數(shù)返回零,最后一個參數(shù)byParam的含義見后面的解釋。
異步發(fā)送接收服務函數(shù):
在一個簡單的系統(tǒng)或多機通訊系統(tǒng)中的從機上,一般情況下不需要復雜的停等的工作模式,而且往往單片機需要對硬件進行控制和檢測,不允許長時間的停下來檢測通訊,但又要求當需要通訊時需要盡快的反應速度,這時就需要使用異步發(fā)送和接收服務函數(shù)。
使用異步發(fā)送和接收服務函數(shù)需要在Config.h文件中定義SCOMM_AsyncInterface宏。
同樣提供兩個服務函數(shù):
voidSendPackage(BYTE*pbyData,BYTEbyLen);
發(fā)送數(shù)據(jù)包,參數(shù)pbyData為將要改善的數(shù)據(jù)包的緩沖區(qū)指針,byLen為將要發(fā)送的數(shù)據(jù)包的長度。
這里的函數(shù)的接口與同步發(fā)送和接收的服務函數(shù)相同。關于這里的細節(jié),見后面對同步和異步服務函數(shù)的說明。
voidAsyncRecePackage(BYTEbyParam);
接收數(shù)據(jù)包,參數(shù)byParam的意義見后面的描述。
使用異步通訊需要用戶定義一個回調(diào)函數(shù),原型如下:
voidOnRecePackage(BYTE*pbyData,BYTEbyBufLen);
當異步接收服務函數(shù)接收到數(shù)據(jù)包之后,調(diào)用OnRecePackage回調(diào)函數(shù),在pbyData指定的緩沖區(qū)中存放數(shù)據(jù)包,byBufLen為數(shù)據(jù)包的長度。
在Config.h文件中定義宏SCOMM_TIMEOUT可以設定異步接收的超時值,當開始接收數(shù)據(jù)包,但沒有收完數(shù)據(jù)而發(fā)生了SCOMM_TIMEOUT次時鐘中斷后,認為接收超時,將已接收到的數(shù)據(jù)刪除。
同步和異步通訊服務函數(shù):
有些情況下,比如一個通訊系統(tǒng)中,由一臺計算機通過串口控制主機,主機通過串口連接很多從機,主機的串口采用分時復用,在這樣的模型中,主機和控制計算機之間的通訊可以使用,異步通訊方式,而主機與從機可以使用同步通訊方式。而同步和異步的發(fā)送函數(shù)接口是相同的,在這樣的情況下,發(fā)送都是同步的。在這樣的模型中,當使用不同的接收函數(shù)之前,需要注意清除接收緩沖區(qū)中的內(nèi)容,通訊模塊提供函數(shù):ClearReceBuffer來做到這一點,此函數(shù)原型如下:
voidClearReceBuffer();
通訊過程中,數(shù)據(jù)包往往是有固定的格式的,這種格式需要根據(jù)用戶所使用的協(xié)議的不同而不同。同步和異步接收服務函數(shù)支持從接收到的數(shù)據(jù)中識別出一定格式的數(shù)據(jù)包。
舉例說明:目前使用的協(xié)議決定數(shù)據(jù)包的格式為固定的包頭0xff,固定的長度4個字節(jié)。其它的細節(jié)在這里不重要,所以忽略掉。
評論