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