《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 通信與網(wǎng)絡(luò) > 業(yè)界動態(tài) > 多功能物流手持終端集群通信方式的設(shè)計與實現(xiàn)

多功能物流手持終端集群通信方式的設(shè)計與實現(xiàn)

《電子技術(shù)應(yīng)用》2007年第2期
2008-01-04
作者:周曉光, 周曉雄

摘 要:為了提高物流行業(yè)的調(diào)度效率,提出了基于Windows CE.NET在多功能物流終端中實現(xiàn)模擬集群無線通信的方案,?;赪indows CE.NET的多" title="的多">的多線程機制,討論了該通信過程中線程間的數(shù)據(jù)同步,、通信協(xié)議的解析以及數(shù)據(jù)的分離等問題,,并在eMbedded Visual C++ 4.0環(huán)境下實現(xiàn)集群模塊與多功能物流手持終端" title="手持終端">手持終端之間的通信。
關(guān)鍵詞:多功能物流手持終端? 集群通信? 協(xié)議幀格式? 串口" title="串口">串口通信? 多線程通信

?

??? 在現(xiàn)代企業(yè)中降低商品成本的一個重要方法就是降低貨物在流通中的成本,,貨物的流通速度直接影響到生產(chǎn)的各個環(huán)節(jié),,物流(Logistics)在現(xiàn)代經(jīng)濟的發(fā)展中起著越來越重要的作用。不論是企業(yè)的物流部門還是專門的物流公司都面臨著調(diào)度效率的問題,。提高調(diào)度效率的方法是在提高物流管理技術(shù)的同時實現(xiàn)物流技術(shù)的信息化,,提高物流技術(shù)信息化的程度。雖然國內(nèi)在物流行業(yè)里也引進了信息化,,但信息化的程度與國外相比還是低得多,。國內(nèi)的物流終端主要集中在車載型且功能相對簡單,,這樣調(diào)度的實時性比較差。
??? 模擬集群通信(Analog Trunking Communication)技術(shù)已經(jīng)相對比較成熟,,強大的調(diào)度功能,、組呼功能和快速呼叫的特性使得集群通信深受大企業(yè)或集團公司的青睞。對于物流行業(yè)而言,,集群通信技術(shù)也是其信息化的一個方向,,通過無線調(diào)度實現(xiàn)快速、便捷,、有效的貨物投遞,、配送,實現(xiàn)有效的實時無線調(diào)度,,提高其調(diào)度效率,。這里的物流終端是集手機、數(shù)字集群,、模擬集群,、GPS定位、條碼掃描,、無線上網(wǎng),、快速打印等功能于一體的集成度很高的多功能手持終端,針對不同的用戶可以方便快捷地進行不同的功能模塊配置,。
????以下將討論在基于Windows CE.NET的多功能物流手持終端上如何用多線程編程實現(xiàn)其與集群模塊通信,,以及如何解析集群模塊中發(fā)往手持終端的數(shù)據(jù)。
1 集群模塊與手持終端通信協(xié)議幀格式
??? 集群通信中的協(xié)議幀格式如下:
?? ?SYNC + LENGTH + DIR + COMMAND + DATA +
??? CHECKSUM
??? SYNC:??0x96 (包頭)
??? LENGTH:?DIR(1B)+COMMAND(1B)+DATA(nB) +
??? CHECKSUM(1B)
??? DIR:??0x80 或0x81?
??? COMMAND:?協(xié)議號
??? DATA:??協(xié)議數(shù)據(jù)
??? CHECKSUM:?SYNC ^ LENGTH ^ DIR ^ COMMAND ^
?????????? ??? DATA? 即全部字節(jié)的異或
??? 其中為了保證通信正常完成,,LENGTH約定要不大于125字節(jié),;?DIR?表示發(fā)送方向: ?0x80表示 上位機>>下位機,?0x81表示下位機>>上位機,;(上位機指手持終端,,下位機指集群模塊);DATA長度不大于122個字節(jié),;COMMAND表示協(xié)議命令包括0x10,0x11,0x12, 0x13,0x15,0x16等,;CHECKSUM是數(shù)據(jù)結(jié)束校驗位,判斷數(shù)據(jù)報是否結(jié)束,。
??? 在該協(xié)議中漢字采用國標(biāo)碼進行傳輸,,其他字符或數(shù)字等都采用ASCII碼進行顯示或發(fā)送,在這個協(xié)議中字符都有特殊意義,,例如:‘<’ 表示下翻,, ‘>’ 表示上翻,‘C’表示清除等,。
2 Windows CE.NET多線程機制
??? ?Windows CE.NET中線程類似于Windows XP中的線程,,每個進程都有一個主線程" title="主線程">主線程,,而且還可以創(chuàng)建任意多個子線程,但受系統(tǒng)存儲器大小和堆棧大小的約束,,實際上在一個進程中不能創(chuàng)建過多的線程,。
  線程是在創(chuàng)建它的進程的地址空間中執(zhí)行代碼,并且在該進程的地址空間中進行數(shù)據(jù)操作,。一個進程的地址空間中可以有多個線程來共享使用,,這個進程的所有線程可以執(zhí)行相同的代碼,對相同的數(shù)據(jù)進行操作,,而且這些線程還可以共享相同的內(nèi)核對象句柄,。多個線程既然可以執(zhí)行相同的代碼并對相同的數(shù)據(jù)進行操作,就會產(chǎn)生在一個程序里如何控制數(shù)據(jù)同步的問題,。這也是多線程編程的一個難點。Windows CE.Net環(huán)境下控制線程同步的方法很多,,但用起來也很容易出問題,。常用的控制線程同步的方法有:
??? (1)事件對象(Event Object)機制。事件對象是一種在通知狀態(tài)或不在通知狀態(tài)的同步對象,,線程可以通過捕獲事件來達到同步,。可以創(chuàng)建手動或者自動復(fù)位的事件對象,,通過命名和共享事件對象來達到不同線程或進程之間的同步,。
??? (2)信號量" title="信號量">信號量(Semaphores)。信號量是通過計數(shù)來控制進程或線程間同步的,,只要信號量的計數(shù)值大于0,,信號量就可以被使用。當(dāng)計數(shù)計到0時該信號量就處于不可用狀態(tài),,它所控制的資源就不可用,,直到其他線程釋放了該信號量使得計數(shù)值大于0才可用。適合多個線程間的通信,。
??? (3)互斥量(Mutexes),。當(dāng)一個線程獲得該互斥量時,該互斥量就被鎖定,,其他線程就不能使用,,直到該互斥量被釋放。??

  當(dāng)然還有其他的方法來控制線程的同步,。多線程通過線程間的通信可以達到同步,,節(jié)省系統(tǒng)資源,減少損耗,。在接下來的串口通信中選擇了事件觸發(fā)機制來控制線程的運行,。
3 集群模塊與手持終端的通信以及數(shù)據(jù)的提取和分析
  集群模塊負(fù)責(zé)接收調(diào)度中心或其他終端發(fā)出的信號,,手持終端自身的CPU負(fù)責(zé)處理模塊接收的信息。手持終端的CPU與集群模塊之間通過串口進行通信,,首先設(shè)定串口參數(shù)如下:
??? 波特率?????????????????? 9 600bps
??? 數(shù)據(jù)位?????????????????? 8bit
??? 校驗位?????????????????? 無
??? 停止位?????????????????? 1 bit
????串口參數(shù)的設(shè)定以及串口操作在這里通過Windows CE.NET自帶的API函數(shù)來完成,,其步驟是:
????(1)打開串口
???? HANDLE? hComPort = CreatFileCreateFile(pszDevName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING, 0, NULL);
??? 其中,pszDevName表示要打開的串口號,,在Windows CE系統(tǒng)中其形式應(yīng)該為TEXT(“COM1:”)或L“COM1:”,,這與UNICODE相一致,當(dāng)串口打開成功,,hComPort應(yīng)該返回打開的串口句柄,,失敗則返回INVALID_HANDLE_VALUE。
??? (2)按上述要求設(shè)定串口參數(shù)
????定義一個DCB結(jié)構(gòu)變量dcb,,然后依次設(shè)定該結(jié)構(gòu)的參數(shù):
?? ?dcb.DCBlength = sizeof (dcb);
??? GetCommState (hLocal, &dcb);???//獲得當(dāng)前串口的參數(shù)放到當(dāng)前dcb中
??? dcb.BaudRate = CBR_9600; ?????? //設(shè)定串口波特率為要求的9600bps
??? dcb.fParity = FALSE;??? ???//設(shè)定校驗位為無
??? dcb.fNull = FALSE;
??? dcb.StopBits = ONESTOPBIT;? ??//設(shè)定一位停止位
??? dcb.Parity = NOPARITY;? ?????? //低4位校驗設(shè)置為否
??? dcb.ByteSize = 8;????? ???? //數(shù)據(jù)位設(shè)定為8位
??? SetCommState (hLocal, &dcb); ?
??????? //把設(shè)定的參數(shù)寫入串口設(shè)定
?? ?設(shè)定串口時間常數(shù):設(shè)定一個COMMTIME OUTS結(jié)構(gòu)變量cto
??? cto.ReadIntervalTimeout = 0; ?
??????? //讀取兩個字符間隔時間設(shè)定
?? ?cto.ReadTotalTimeoutMultiplier = 0;???? //設(shè)定
??? cto.ReadTotalTimeoutConstant = 0;????//設(shè)定讀超時時間為無限
??? cto.WriteTotalTimeoutMultiplier = 0;????//設(shè)定寫超時時間為無限時
??? SetCommTimeouts (hLocal, &cto); //把時間設(shè)定寫進串口
??? 至此,串口初始化編程設(shè)定完畢,。
??? 由于這里涉及實時收發(fā)數(shù)據(jù),為了提高主線程響應(yīng)其他事件的速度,,在主線程中創(chuàng)建一個獨立的子線程來監(jiān)聽串口,,通過觸發(fā)事件EV_RXCHAR通知線程去讀串口緩沖區(qū)來得到數(shù)據(jù)。主線程與子線程的調(diào)度關(guān)系如圖1所示,。

?

?


????主線程負(fù)責(zé)處理主窗口及其控件的消息以及子線程發(fā)送過來的消息,,子線程主要負(fù)責(zé)處理串口消息及數(shù)據(jù),大大減小了主線程響應(yīng)事件的壓力,提高了系統(tǒng)的響應(yīng)速度,。
????以下討論如何操作子線程讓其很好地收發(fā)并解析數(shù)據(jù),。
 ? 串口監(jiān)聽線程程序流程圖如圖2所示。從中可以看出線程中設(shè)定了事件EV_RXCH-AR,,當(dāng)線程守候到該消息后執(zhí)行讀串口事件,,否則線程繼續(xù)等待該消息,這樣既節(jié)省系統(tǒng)資源,,也省去不斷地讀串口,,減少了資源消耗。

?


??? 其中,,串口初始化部分已經(jīng)在前面介紹了,,其余程序的簡單實現(xiàn)如下:
??? hRecvThread = CreateThread(NULL, 0, ReceiveProc, hWnd, 0, &dwStat); ???//創(chuàng)建接收線程監(jiān)聽串口
?? ?if (hRecvThread)
???? ??CloseHandle (hRecvThread);
???? 如果子線程創(chuàng)建成功,則線程啟動轉(zhuǎn)入線程處理函數(shù)(RecvProc)處理接收來的數(shù)據(jù),。
???? RecvProc實現(xiàn)對串口的監(jiān)聽,,實時接收從集群模塊發(fā)到串口的數(shù)據(jù)。為了實現(xiàn)這一實時功能,,通過串口信號觸發(fā)一個事件來通知程序去接收數(shù)據(jù),,這樣既可以比較準(zhǔn)確地接收數(shù)據(jù),也可以減少處理器不斷查詢串口對系統(tǒng)資源的消耗,。下面是簡化的線程處理函數(shù)的實現(xiàn):
??? DWORD WINAPI RecvProc(PVOID pArg) {
??? PurgeComm(hComPort, PURGE_RXCLEAR);
??????????? //清空串口的讀緩沖區(qū)
??? SetCommMask (hComPort, EV_RXCHAR);
?? ?????????? //設(shè)定串口讀事件EV_RXCHAR
??? while (TRUE)
??? {
?? ?if(WaitCommEvent(hComPort, &evtMask, 0)) {
? ????????????? // 等待串口EV_RXCHAR事件的發(fā)生
??? SetCommMask(hComPort, EV_RXCHAR);
 ??????? //如果事件發(fā)生則重新設(shè)定事件以便下次能再觸發(fā)
??? if(evtMask&EV_RXCHAR)
??? {???? ?????????????????????? //串口有數(shù)據(jù)讀入
??? ClearCommError(hComPort,&dwReadErrors, &cmState);
??? willreadlen = cmState.cbInQue;
???????????????? //查看串口讀緩沖區(qū)里數(shù)據(jù)的實際長度
 ? if (willreadlen <= 0) {
    continue;
 ? }
 ? memset(recvText, '0', sizeof(recvText));
??? if(!ReadFile (hComPort, recvText, willreadlen, &cBytes, 0)) //讀串口數(shù)據(jù)到
 ?{
   ?if(hComPort= =INVALID_HANDLE_VALUE)
   ?return 0;
?? ?}
??? …… //按照數(shù)據(jù)包的定義從串口數(shù)據(jù)中提取一個完整的包
   ???????? }
    }
 ?}
??? 程序至此完成從串口緩沖區(qū)讀數(shù)據(jù)的過程,,下一步程序設(shè)計的任務(wù)是如何分析分離數(shù)據(jù),。
 ? 根據(jù)數(shù)據(jù)協(xié)議格式可以知道,這里的數(shù)據(jù)包有相同的包頭(0x96),,通過包頭和數(shù)據(jù)長度(LENGTH)就可以把數(shù)據(jù)分離成一個個數(shù)據(jù)包,,再根據(jù)協(xié)議號(COMMAND)的不同可以完全解析出該數(shù)據(jù)的含義,從而對數(shù)據(jù)做出相應(yīng)的決策(送上顯示或報警等),。以下給出一段解析數(shù)據(jù)包的示例:假設(shè)數(shù)據(jù)包存放在數(shù)組RecvText中,,則:
??? command = RecvText[3];
??? switch(command){? //由協(xié)議號來解析數(shù)據(jù)
 ? case 0x12: //數(shù)據(jù)送到上面界面顯示
????if(RecvText[4] == 0x01){?
????????? //表示送到主窗口的第一行顯示
 ? ??……
?? ?}
??? else{ ????? //表示送主窗口的第二行顯示
    ……
  ??}
  ??break;
??? case 0x13: ?//提取手持機電池電量和集群信號強度,
???? 為判斷手持機能否工作提供提示
??? ?if(RecvText[4] = = 0x01){
 ????????? //表示該數(shù)據(jù)包為顯示信號強度
??????? …… //把RecvText[5](表信號強度值)進行處理
?????????? }
?????????? else{ ??????? //表示該數(shù)據(jù)包數(shù)據(jù)是電池電量
??? ?? …… ?????//發(fā)到界面顯示電池電量
?????????? }
?????????? break;??????????????????????????????????????????
??? ?case 0x15: ??//進入或退出讀出或設(shè)置集群模塊內(nèi)部具體地址空間的數(shù)據(jù)狀態(tài)
   ???? ……
   ???? break;
???? case 0x16: ????? //在進入讀取集群模塊內(nèi)部數(shù)據(jù)狀態(tài)后,,讀取或設(shè)置具體地址空間的值
   ???? ……
   ???? break;
  ?}
  該程序內(nèi)部具體的實現(xiàn)依據(jù)界面不同其內(nèi)部函數(shù)實現(xiàn)也不同,,這里不一一羅列了。
  至此程序完成了集群模塊與手持終端間的通信功能,,實現(xiàn)了對下位機發(fā)往上位機數(shù)據(jù)的分離與解析,,為上層界面對數(shù)據(jù)的處理做好了充分的準(zhǔn)備。
??? 以上討論了集群模塊與多功能物流手持終端之間通信的協(xié)議格式,,Windows CE.NET的多線程機制,,以及如何利用多線程實現(xiàn)集群模塊與手持終端之間的通信,并對數(shù)據(jù)的分離解析以及串口的配置作了討論,。通過對應(yīng)用程序的設(shè)計,可以完全實現(xiàn)集群模塊與手持終端之間的通信以及數(shù)據(jù)分離解析,,為上層界面提供完整的數(shù)據(jù)服務(wù),,使該終端能實現(xiàn)集群通信功能,滿足物流行業(yè)方便快捷調(diào)度的需要,。上述程序在eMbedded Visual C++ 4.0環(huán)境下編譯,,下載到Windows CE.NET 的手持終端上能正常穩(wěn)定地運行,并且其功能與專門的對講機相比具有更好的可視性,、操作更靈活的特點,。
參考文獻
[1]? 汪 斌,李存斌,,陳鵬等. EVC高級編程及其應(yīng)用開發(fā),北京:中國水利電力出版社,2005.
[2] ?BOLING D. Programming Microsoft Windows CE. NET,?Third Edition, Microsoft Press, 2003.
[3] ?周毓林. Windows CE.NET內(nèi)核定制及應(yīng)用開發(fā).北京:?電子工業(yè)出版社,2005.

?

?

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點,。轉(zhuǎn)載的所有的文章,、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有,。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者,。如涉及作品內(nèi)容、版權(quán)和其它問題,,請及時通過電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,,避免給雙方造成不必要的經(jīng)濟損失。聯(lián)系電話:010-82306118,;郵箱:[email protected],。