![多個(gè)串口設(shè)備數(shù)據(jù)的連續(xù)采集參考PPT_第1頁(yè)](http://file1.renrendoc.com/fileroot_temp2/2021-1/26/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d5/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d51.gif)
![多個(gè)串口設(shè)備數(shù)據(jù)的連續(xù)采集參考PPT_第2頁(yè)](http://file1.renrendoc.com/fileroot_temp2/2021-1/26/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d5/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d52.gif)
![多個(gè)串口設(shè)備數(shù)據(jù)的連續(xù)采集參考PPT_第3頁(yè)](http://file1.renrendoc.com/fileroot_temp2/2021-1/26/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d5/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d53.gif)
![多個(gè)串口設(shè)備數(shù)據(jù)的連續(xù)采集參考PPT_第4頁(yè)](http://file1.renrendoc.com/fileroot_temp2/2021-1/26/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d5/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d54.gif)
![多個(gè)串口設(shè)備數(shù)據(jù)的連續(xù)采集參考PPT_第5頁(yè)](http://file1.renrendoc.com/fileroot_temp2/2021-1/26/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d5/f6db6023-6bb6-4f2c-ad01-36fe0b91c1d55.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、工控程序設(shè)計(jì),2,學(xué)習(xí)情景2.4 多個(gè)串口設(shè)備數(shù)據(jù)的連續(xù)采集,學(xué)習(xí)情景2.4 多個(gè)串口設(shè)備數(shù)據(jù)的連續(xù)采集,2.4.1 學(xué)習(xí)要點(diǎn) 1.知識(shí)點(diǎn): 煤礦鉆機(jī)性能檢測(cè)設(shè)備的數(shù)據(jù)通信協(xié)議,數(shù)據(jù)幀的校驗(yàn)方法 2.技能點(diǎn): 校驗(yàn)碼的計(jì)算,上位機(jī)主動(dòng)模式串口通信類的設(shè)計(jì),HC-100智能測(cè)控儀、JW-2A扭矩儀、LU-902M位式調(diào)節(jié)儀數(shù)據(jù)采集 2.4.2 任務(wù)描述 在前一個(gè)情景中實(shí)現(xiàn)了對(duì)單個(gè)HSDZC電能綜合測(cè)試數(shù)據(jù)的接收。在鉆機(jī)性能測(cè)試系統(tǒng)中,還需要使用JW-2A扭矩儀、HC-100智能測(cè)控儀、LU-902M位式調(diào)節(jié)儀來采集其它參數(shù)的值,而這些設(shè)備的數(shù)據(jù)通信規(guī)則不同,所以必須對(duì)每種設(shè)備編寫通信程序,并同步
2、、連續(xù)地采集多個(gè)設(shè)備的數(shù)據(jù)。 該教學(xué)情景中先針對(duì)上位機(jī)主動(dòng)通信模式設(shè)計(jì)基類CActiveCOMHelper,再分別對(duì)三種不同的儀器分別設(shè)計(jì)派生類來進(jìn)行數(shù)據(jù)管理,實(shí)現(xiàn)對(duì)多個(gè)不同設(shè)備進(jìn)行同步、連續(xù)的數(shù)據(jù)采集,2.4.3 相關(guān)知識(shí) 1 煤礦鉆機(jī)性能檢測(cè)設(shè)備的數(shù)據(jù)通信協(xié)議 (1) HC-100智能測(cè)控儀 HC-100智能測(cè)控儀可以使用RS232、RS485接口與計(jì)算機(jī)通訊,數(shù)據(jù)格式為1個(gè)起始位,8個(gè)數(shù)據(jù)位,無奇偶校驗(yàn),1個(gè)停止位,共11位。設(shè)備的所有數(shù)字變換成ASCII碼進(jìn)行傳輸:例如:儀表編號(hào)Addr=01,測(cè)量值=123.4,則數(shù)據(jù)千位為31H、百位為32H、十位為33H、小數(shù)點(diǎn)為2EH,個(gè)位為3
3、4H,符號(hào)位2BH為正,2DH為負(fù)。 從儀表讀數(shù)據(jù)的指令格式為:EOT+儀表地址編號(hào)+52H+參數(shù)+ENQ 表2.4.1 發(fā)送給HC100的數(shù)據(jù)格式,儀表返回?cái)?shù)據(jù)的格式為:STX+儀表地址編號(hào)+符號(hào)位+測(cè)量值+校驗(yàn)碼+ETX。其中的數(shù)據(jù)參數(shù)值為符號(hào)位+4位有效位+小數(shù)點(diǎn),共6位,校驗(yàn)碼為前面發(fā)送的9個(gè)字節(jié)之和。 表2.4.2 HC100返回的數(shù)據(jù)格式,HC-100智能控制儀的數(shù)據(jù)處理流程如圖2.4.1所示,圖2.4.1 HC-100智能控制儀數(shù)據(jù)處理流程,2)JW-2A扭矩儀 JW-2A扭矩儀采用多機(jī)通訊方式,本機(jī)地址為0AH。數(shù)據(jù)位8位,停止位1位。波特率可用跳線選擇4800bps或2400
4、bps。奇偶位在這里做地址和數(shù)據(jù)判別位,1為地址,0為數(shù)據(jù)。儀器只被地址觸發(fā),即上位機(jī)只有向儀器發(fā)0AH,并且奇偶位為1時(shí),才能得到儀器的響應(yīng)。儀器被本機(jī)地址觸發(fā)后,向上位機(jī)傳回本機(jī)地址,然后等待上位機(jī)發(fā)來的命令。受到命令后,根據(jù)命令執(zhí)行不同的任務(wù)。命令為一個(gè)字節(jié)。目前有效的命令有15個(gè),下面敘述各命令代表的任務(wù)。 0:讀扭矩轉(zhuǎn)速 儀器受到命令后向上位機(jī)依次傳送扭矩,轉(zhuǎn)速,采樣時(shí)間3個(gè)參數(shù)。扭矩、轉(zhuǎn)速為浮點(diǎn)數(shù),每個(gè)參數(shù)4個(gè)字節(jié)。采樣時(shí)間為整數(shù),2個(gè)字節(jié)。每個(gè)參數(shù)的傳送順序都是從內(nèi)存的低地址到高地址 1:存儲(chǔ)操作。在測(cè)量狀態(tài)收到此命令,將啟動(dòng)存儲(chǔ)操作;在存儲(chǔ)狀態(tài)收到此命令,將退出存儲(chǔ)狀態(tài)。 2:
5、讀儀器存儲(chǔ)的數(shù)據(jù)數(shù)組。在非存儲(chǔ)狀態(tài)收到此命令,將向上位機(jī)傳送春初數(shù)據(jù)的數(shù)組。 3:釋放操作。在測(cè)量狀態(tài)收到此命令,將啟動(dòng)釋放操作;在釋放狀態(tài)儀器不再接受命令,4:扣除/不扣除轉(zhuǎn)換。在扣除狀態(tài)收到此命令,將退出扣除狀態(tài);在非扣除狀態(tài)收到此命令,將進(jìn)入扣除狀態(tài)。 5:內(nèi)/外轉(zhuǎn)速顯示轉(zhuǎn)換。在顯示內(nèi)轉(zhuǎn)速時(shí)收到此命令,將顯示外轉(zhuǎn)速;在顯示外轉(zhuǎn)速時(shí)收到此命令,將顯示內(nèi)轉(zhuǎn)速。 6:調(diào)零操作。儀器才測(cè)量狀態(tài)收到此命令,將啟動(dòng)調(diào)零操作。 7:讀儀器狀態(tài)。儀器收到命令后向上位機(jī) 傳送儀器狀態(tài)字節(jié)。狀態(tài)字節(jié)各位的定義如表2.4.3所示。 表2.4.3 JW-2A通信協(xié)議,8:讀模擬通道數(shù)據(jù)。儀器收到命令后向上位機(jī)依
6、次傳送0至7通道的A/D采樣結(jié)果。每通道2字節(jié),高位在前。低14位表示數(shù)值大小,最高2位表示小數(shù)點(diǎn)位置。小數(shù)點(diǎn)位置為0,有0位小數(shù)點(diǎn);小數(shù)點(diǎn)位置為1,有1位小數(shù)點(diǎn);小數(shù)點(diǎn)位置為2,有2位小數(shù)點(diǎn)。 9:讀0點(diǎn)。儀器收到命令后向上位機(jī)依次傳送10個(gè)零點(diǎn)值和其相應(yīng)的轉(zhuǎn)速值。每個(gè)零點(diǎn)6個(gè)字節(jié)(前4個(gè)字節(jié)是零點(diǎn),浮點(diǎn)數(shù),后2個(gè)字節(jié)是轉(zhuǎn)速,無符號(hào)整數(shù),高位在前),共60個(gè)字節(jié)。 10:寫零點(diǎn)。儀器受到命令后準(zhǔn)備接受10個(gè)零點(diǎn),共60個(gè)字節(jié)的數(shù)據(jù)。上位機(jī)應(yīng)按上述讀零點(diǎn)的順序依次將60個(gè)字節(jié)寫回去。注意,寫零點(diǎn)不能少于60字節(jié)。 11:讀扭矩參數(shù)。儀器收到命令后向上位機(jī)依次傳送11個(gè)參數(shù),共24個(gè)字節(jié)。這11
7、個(gè)參數(shù)的排列順序,數(shù)據(jù)類型,數(shù)據(jù)長(zhǎng)度如表2.4.4所示。 12:寫扭矩參數(shù)。儀器收到命令后準(zhǔn)備接受11個(gè)參數(shù),共24個(gè)字節(jié)的數(shù)據(jù)。上位機(jī)應(yīng)按上述讀扭矩參數(shù)的順序依次將24個(gè)字節(jié)寫回去。注意:寫扭矩參數(shù)不能少于24字節(jié)。 13:讀模擬通道量程。儀器收到命令后向上位機(jī)依次傳送8個(gè)通道的量程值。每個(gè)量程2個(gè)字節(jié),共16個(gè)字節(jié)。數(shù)據(jù)類型是無符號(hào)整數(shù),高位在前。低14位表示數(shù)值大小,最高2位表示小數(shù)點(diǎn)位置。小數(shù)點(diǎn)位置為0,有0位小數(shù)點(diǎn);小數(shù)點(diǎn)位置為1,有1位小數(shù)點(diǎn),小數(shù)點(diǎn)位置為2,有2位小數(shù)點(diǎn),表2.4.4 JW-2A的扭矩參數(shù),14:寫模擬通道量程。儀器收到命令后準(zhǔn)備接收8個(gè)通道的量程表。每個(gè)量程2個(gè)
8、字節(jié),共16個(gè)字節(jié)。數(shù)據(jù)類型是無符號(hào)整數(shù),高位在前。低14位表示數(shù)值大小,最高2位表示小數(shù)點(diǎn)位置。小數(shù)點(diǎn)位置為0,有0位小數(shù)點(diǎn);小數(shù)點(diǎn)位置為1,有1位小數(shù)點(diǎn),小數(shù)點(diǎn)位置為2,有2位小數(shù)點(diǎn)。上位機(jī)應(yīng)按上述讀模擬通道量程的順序依次將16個(gè)字節(jié)寫回去。需要注意的是:寫模擬通道量程不能少于16字節(jié),JW-2A扭矩儀的數(shù)據(jù)采用IEEE浮點(diǎn)數(shù)形式表示,需要作浮點(diǎn)數(shù)字節(jié)數(shù)組到浮點(diǎn)數(shù)的轉(zhuǎn)換。如果用DCBA表示浮點(diǎn)數(shù),D為高位,A為低位,每個(gè)字母表示一個(gè)字節(jié),那么DCBA依次為 SXXX XXXX XMMM MMMM MMMM MMMM MMMM MMMM,其中S代表符號(hào),1位,1表示負(fù),0表示正,X代表指數(shù),
9、8位,0到255轉(zhuǎn)換為-127到128,M代表尾數(shù),23位,注意尾數(shù)總共24位,最高位等于1是隱含的。 JW-2A扭矩儀的數(shù)據(jù)處理流程如圖2.4.2所示,圖2.4.2 JW2A數(shù)據(jù)處理流程,另外,儀器處于釋放狀態(tài)時(shí),每釋放一組數(shù)據(jù)都會(huì)將數(shù)據(jù)從串口發(fā)送出來。數(shù)據(jù)格式和發(fā)送的順序同于用0命令讀扭矩轉(zhuǎn)速。 (3)LU-902M位式調(diào)節(jié)儀 LU-902M采用串行異步通訊,提供RS232C、422A或者485通訊接口,波特率有1200、2400、4800、9600四種選擇。每幀數(shù)據(jù)包含1個(gè)起始位(第0位),8個(gè)數(shù)據(jù)位(第1-8位),1個(gè)“尋址/數(shù)據(jù)”選擇位(第9位,決定指令類別),1個(gè)停止位,共11位,
10、數(shù)據(jù)采用16進(jìn)制表達(dá)。在每個(gè)通訊指令中,儀表最后返回信息4FH、4BH表示通訊成功,返回3FH,3FH表示通訊失敗。 1)尋址指令 當(dāng)上位機(jī)要對(duì)某LU-902M儀表進(jìn)行通訊操作時(shí),應(yīng)先對(duì)其發(fā)尋址指令。尋址指令為單字節(jié)指令,第1-8位為地址,第9位(校驗(yàn)位)為“1”(非尋址指令為“0”)。 2)數(shù)據(jù)讀取指令 指令格式:45H 儀表返回:PV、SV、MV、4FH、4BH 其中PV為測(cè)量值、SV為設(shè)定值、MV為輸出值,各占兩個(gè)字節(jié),低字節(jié)在前高字節(jié)在后。 3)讀參數(shù)指令 指令格式:52H + 參數(shù)代碼 儀表返回:參數(shù)值 + 4FH、4BH 4)寫參數(shù)指令 指令格式:57H + 參數(shù)代碼 + 參數(shù)值
11、儀表返回:4FH、4BH 5)結(jié)束指令 指令格式:4FH或第9位為“1”的非本機(jī)尋址指令 儀表無返回,2 數(shù)據(jù)幀的校驗(yàn) 數(shù)據(jù)幀校驗(yàn)的目的是為了檢查接收到的數(shù)據(jù)幀的完整性和準(zhǔn)確性。和校驗(yàn)位不同,校驗(yàn)位的作用是保證一個(gè)數(shù)據(jù)單位的正確性,是從微觀角度考慮。形象地說,校驗(yàn)位保證一個(gè)字正確,數(shù)據(jù)幀校驗(yàn)是保證一段話正確。 對(duì)數(shù)據(jù)幀進(jìn)行校驗(yàn)的方法是:發(fā)送方根據(jù)要發(fā)送的數(shù)據(jù)幀,利用某種算法計(jì)算出若干字節(jié)的校驗(yàn)碼,并把校驗(yàn)碼附加在數(shù)據(jù)幀中發(fā)送給接收端,接收端接收到數(shù)據(jù)后,分離出校驗(yàn)碼和數(shù)據(jù)本身,再根據(jù)發(fā)送方的算法,計(jì)算出校驗(yàn)碼,如果和接收到的校驗(yàn)碼一致,則認(rèn)為接收到的數(shù)據(jù)準(zhǔn)確無誤。串口通信中常用的校驗(yàn)方式有累加
12、和校驗(yàn)、異或和校驗(yàn)、循環(huán)冗余校驗(yàn)等。 (1)累加和校驗(yàn) 累加和校驗(yàn)的過程是,發(fā)送端將數(shù)據(jù)的每個(gè)字節(jié)累加求和,然后截取最低字節(jié)(或最低兩字節(jié))作為校驗(yàn)碼發(fā)送給接收端,接收端收到數(shù)據(jù)后,用同樣的方法計(jì)算累加和,并與發(fā)送過來的校驗(yàn)碼進(jìn)行比較,從而檢驗(yàn)發(fā)送的數(shù)據(jù)是否有誤。 (2)異或和校驗(yàn) 異或和校驗(yàn)的過程是,發(fā)送端取出發(fā)送數(shù)據(jù)的第1個(gè)字節(jié),與后續(xù)每個(gè)字節(jié)依次按位異或,然后將計(jì)算結(jié)果(1個(gè)字節(jié))作為校驗(yàn)碼發(fā)送給接收端,接收端收到數(shù)據(jù)后,用同樣的方法計(jì)算異或和,并與發(fā)送過來的校驗(yàn)碼進(jìn)行比較,從而檢驗(yàn)發(fā)送的數(shù)據(jù)是否有誤,3)循環(huán)冗余校驗(yàn) 循環(huán)冗余校驗(yàn)(Cyclical Redundancy Check)簡(jiǎn)
13、稱CRC,它利用除法及余數(shù)的原理來作錯(cuò)誤偵測(cè)。實(shí)際應(yīng)用時(shí),發(fā)送端計(jì)算出校驗(yàn)碼值并附加在數(shù)據(jù)幀中發(fā)送給接收端,接收端對(duì)收到的數(shù)據(jù)重新計(jì)算校驗(yàn)碼并與收到的校驗(yàn)碼相比較,若兩個(gè)值不同,則說明數(shù)據(jù)通訊出現(xiàn)錯(cuò)誤,要求發(fā)送端重新發(fā)送。 常用的CRC標(biāo)準(zhǔn)有CRC-12、CRC-16、CRC-CCITT和CRC-32,其中CRC-16和CRC-CCITT用來作一個(gè)字節(jié)數(shù)據(jù)的校驗(yàn),在串口數(shù)據(jù)校驗(yàn)中最常用的是CRC-16。下面是循環(huán)冗余校驗(yàn)碼的計(jì)算過程: 1)設(shè)置CRC寄存器,并給其賦值FFFF(hex)。 2)將數(shù)據(jù)的第一個(gè)字節(jié)與16位CRC寄存器的低8位進(jìn)行異或,并把結(jié)果存入CRC寄存器。 3)CRC寄存器向
14、右移一位,MSB(最高有效位)補(bǔ)零,移出并檢查L(zhǎng)SB(最低有效位)。 4)如果LSB為0,重復(fù)第三步;若LSB為1,CRC寄存器與多項(xiàng)式碼相異或。 5)重復(fù)第3與第4步直到8次移位全部完成。此時(shí)一個(gè)字節(jié)數(shù)據(jù)處理完畢。 6)重復(fù)第2至第5步直到所有數(shù)據(jù)全部處理完成。 7)最終CRC寄存器的內(nèi)容即為CRC值。 常用的循環(huán)冗余校驗(yàn)標(biāo)準(zhǔn)多項(xiàng)式為: CRC-16:X16+ X15+X2+1 CRC-CCITT:X16+X12 +X5+1 CRC-32:X32+X26+X23+X16+X12+X11+X10+ X8+X7+X5+X4+X2+X+1 其中CRC-16多項(xiàng)式對(duì)應(yīng)多項(xiàng)式碼為1000 0000 0
15、000 0101(0 x8005),CRC-CCITT對(duì)應(yīng)的多項(xiàng)式碼為0001 0000 0010 0001(0 x1021,2.4.4 任務(wù)實(shí)施 1 校驗(yàn)碼的計(jì)算 在串口通信通,校驗(yàn)碼在保證數(shù)據(jù)幀的正確性方面具有重要作用,雖然在鉆機(jī)性能測(cè)試系統(tǒng)中只用到累加和校驗(yàn),但為了能應(yīng)對(duì)串口通信中可能出現(xiàn)的復(fù)雜情況,下面對(duì)三種校驗(yàn)碼的計(jì)算都進(jìn)行具體實(shí)現(xiàn)。 (1)累加和校驗(yàn)碼的計(jì)算 累加和校驗(yàn)碼可以取累加和的低8位(1個(gè)字節(jié))或低16位(兩個(gè)字節(jié)),在下位機(jī)處理能力允許的情況下采用兩個(gè)字節(jié)作校驗(yàn)碼可以提高校驗(yàn)的準(zhǔn)確度。 下面的C#代碼將累加和校驗(yàn)碼生成功能封裝到CCheck類的方法中,其中CheckSum
16、_1方法計(jì)算單字節(jié)累加和校驗(yàn)碼,CheckSum_2方法計(jì)算雙字節(jié)累加和校驗(yàn)碼 class CCheck /函數(shù)功能: /計(jì)算字節(jié)數(shù)組b中從offset位置開始的count個(gè)元素的單字節(jié)累加和校驗(yàn)碼 /參數(shù): /b:要計(jì)算累加和的字節(jié)數(shù)組 /offset:要計(jì)算累加和的元素的起始位置 /count:要計(jì)算累加和的連續(xù)元素個(gè)數(shù) /返回值:累加和的低8位(單個(gè)字節(jié),public static byte CheckSum_1(byte b, int offset, int count) uint sum = 0; for (int i = offset; i offset + count; i+)
17、sum += bi; /數(shù)組元素累加求和 return (byte)(sum /函數(shù)功能: /計(jì)算字節(jié)數(shù)組b中從offset位置開始的count個(gè)元素的雙字節(jié)累加和校驗(yàn)碼 /參數(shù): /b:要計(jì)算累加和的字節(jié)數(shù)組 /offset:要計(jì)算累加和的元素的起始位置 /count:要計(jì)算累加和的連續(xù)元素個(gè)數(shù) /返回值:長(zhǎng)度為2的字節(jié)數(shù)組,第1個(gè)元素為累加和的低8位 /第2個(gè)元素為累加和的高8位,public static byte CheckSum_2(byte b, int offset, int count) uint sum = 0; byte tmp = new byte2; /存放累加和的低8
18、位和高8位 for (int i = offset; i 8); /高8位在后 return tmp; 下面的測(cè)試程序調(diào)用CheckSum_1方法,計(jì)算出長(zhǎng)度為1個(gè)字節(jié)的累加和校驗(yàn)碼,并附加在字節(jié)數(shù)組末尾: byte b =0 x41,0 x42,0 x43,0; /保留一個(gè)字節(jié)位置存儲(chǔ)校驗(yàn)碼 byte sum = CCheck.CheckSum_1(b, 0, b.Length - 1); /計(jì)算單字節(jié)累加和 bb.Length-1 = sum; /附加在字節(jié)數(shù)組末尾,下面的測(cè)試程序調(diào)用CheckSum_2方法,計(jì)算出長(zhǎng)度為兩個(gè)字節(jié)的累加和校驗(yàn)碼,并附加在字節(jié)數(shù)組末尾: byte b =0
19、x41,0 x42,0 x43,0,0; /保留兩個(gè)字節(jié)位置存儲(chǔ)校驗(yàn)碼 byte sum = CCheck.CheckSum_2(b, 0, b.Length - 2); /計(jì)算雙字節(jié)累加和 bb.Length-2 = sum0; /附加在字節(jié)數(shù)組末尾 bb.Length-1 = sum1; (2)異或和校驗(yàn)碼的計(jì)算 下面的C#代碼將異或和校驗(yàn)碼生成功能封裝到CCheck類的方法中,方法名為XorSum: class CCheck /函數(shù)功能: /計(jì)算字節(jié)數(shù)組b中從offset位置開始的count個(gè)元素的單字節(jié)異或和校驗(yàn)碼 /參數(shù): /b:要計(jì)算累加和的字節(jié)數(shù)組 /offset:要參與計(jì)算校驗(yàn)
20、碼的元素的起始位置 /count:要參與計(jì)算校驗(yàn)碼的連續(xù)元素個(gè)數(shù) /返回值:異或和(8位,1個(gè)字節(jié),public static byte XorSum(byte b, int offset, int count) byte sum = 0; for (int i = offset; i offset + count; i+) sum = bi; /依次和每個(gè)元素進(jìn)行按位異或運(yùn)算 return sum; 下面的測(cè)試程序調(diào)用XorSum方法,計(jì)算出長(zhǎng)度為1個(gè)字節(jié)的異或和校驗(yàn)碼,并附加在字節(jié)數(shù)組末尾: byte b =0 x41,0 x42,0 x43,0; /保留一個(gè)字節(jié)位置存儲(chǔ)校驗(yàn)碼 byte
21、xorsum = CCheck. XorSum(b, 0, b.Length - 1); /計(jì)算異或和 bb.Length-1 = xorsum; /附加在字節(jié)數(shù)組末尾,3)循環(huán)冗余校驗(yàn)碼的計(jì)算 下面的C#代碼將CRC-16校驗(yàn)碼生成功能封裝到CCheck類的方法中,方法名為CRC16: class CCheck /函數(shù)功能: /計(jì)算字節(jié)數(shù)組b中從offset位置開始的count個(gè)元素的循環(huán)冗余校驗(yàn)碼 /參數(shù): /b:要計(jì)算累加和的字節(jié)數(shù)組 /offset:要參與計(jì)算校驗(yàn)碼的元素的起始位置 /count:要參與計(jì)算校驗(yàn)碼的連續(xù)元素個(gè)數(shù) / CrcPoly:CRC多項(xiàng)式對(duì)應(yīng)的16位二進(jìn)制編碼 /
22、返回值:長(zhǎng)度為2的字節(jié)數(shù)組,第1個(gè)元素為校驗(yàn)碼的低8位 /第2個(gè)元素為校驗(yàn)碼的高8位,public static byte CRC16(byte b, int offset, int count, ushort CrcPoly) ushort CrcReg = 0 xFFFF; /16位CRC寄存器 uint LSB; /最低有效位 byte tmp = new byte2; for (int i = offset; i = 1; /CRC寄存器邏輯右移1位 if (LSB = 1) CrcReg = CrcPoly;,tmp0 = (byte)(CrcReg,2 上位機(jī)主動(dòng)模式串口通信類的設(shè)
23、計(jì) 煤礦鉆機(jī)性能測(cè)試系統(tǒng)中用到的HC-100智能測(cè)控儀、JW-2A扭矩儀和LU-902M位式調(diào)節(jié)儀與HSDZC電能綜合測(cè)試儀不同,這些設(shè)備需要上位機(jī)主動(dòng)發(fā)送命令,才給予回復(fù),因此可以把這三種設(shè)備的通信模式歸為“上位機(jī)主動(dòng)模式”。 下面將設(shè)計(jì)上位機(jī)主動(dòng)模式的串口通信類CActiveCOMHelper,和CPassiveCOMHelper類不同的是,CActiveCOMHelper類中增加了一個(gè)名為command的成員,存放當(dāng)前應(yīng)該執(zhí)行的命令,線程函數(shù)根據(jù)該成員的相關(guān)屬性,就知道現(xiàn)在應(yīng)該給下位機(jī)發(fā)送什么命令。由于采用“提問回答”的方式,能夠準(zhǔn)確控制下位機(jī)發(fā)送來的數(shù)據(jù),故不再需要隊(duì)列來暫存接收的數(shù)據(jù)
24、。 CCommand類實(shí)現(xiàn)代碼如下: public class CCommand public string commandName;/命令名字 public byte cmdContent;/命令的內(nèi)容 public Parity parity = Parity.None;/發(fā)送命令時(shí)采用的校驗(yàn)方式 public byte replyContent;/回復(fù)內(nèi)容,public int replyLength;/回復(fù)內(nèi)容的規(guī)定長(zhǎng)度 public bool isCompleted; /命令是否完成 public CCommand() /創(chuàng)建對(duì)象時(shí)commandName不能為null,以免后面比較時(shí)
25、出錯(cuò) mandName = ; command成員(CCommand的實(shí)例)是UI模塊和CActiveCOMHelper對(duì)象的連接紐帶。UI模塊首先查詢前一個(gè)命令是否完成(isCompleted是否為true),若已經(jīng)完成,就設(shè)置下一條命令的名字、內(nèi)容、校驗(yàn)方式、回復(fù)內(nèi)容的規(guī)定長(zhǎng)度,交給CActiveCOMHelper對(duì)象去執(zhí)行;CActiveCOMHelper對(duì)象執(zhí)行完命令后,把回復(fù)內(nèi)容填好,并將完成標(biāo)志isCompleted設(shè)置為true。如此循環(huán),就可以不斷讓CActiveCOMHelper對(duì)象執(zhí)行命令。這樣分工的好處是,處于上層的UI模塊沒有必要知道如何和串口通信、如何創(chuàng)建線程等等復(fù)雜
26、瑣碎的具體操作,而只要知道該發(fā)什么命令,以及如何處理收到的結(jié)果,CActiveCOMHelper類實(shí)現(xiàn)代碼如下: public class CActiveCOMHelper public int readTimeOut;/接收數(shù)據(jù)超時(shí)毫秒數(shù) public string portName;/設(shè)備所占用的串口名 private bool stopFlag;/線程循環(huán)停止標(biāo)志 private int baudRate, dataBits; private StopBits stopBits; private CCommand command; public delegate void DataRec
27、eivedHandler(CActiveCOMHelper sender); public event DataReceivedHandler DataReceived; public CActiveCOMHelper(string portName, int baudRate, int dataBits, StopBits stopBits,this.portName = portName; this.baudRate = baudRate; this.dataBits = dataBits; this.stopBits = stopBits; this.readTimeOut = 3000
28、;/默認(rèn)3000毫秒讀取超時(shí) mand = new CCommand(); /始終保持有一個(gè)命令 mand.isCompleted = true; /該命令開始時(shí)處于完成狀態(tài) public void start() Thread t = new Thread(new ThreadStart(threadFun); t.IsBackground = true; stopFlag = false; t.Start();,public void stop() stopFlag = true; public CCommand getCommand() /獲取一個(gè)克隆的命令對(duì)象 CCommand cmd
29、 = new CCommand(); Monitor.Enter(this); /線程同步:在進(jìn)行g(shù)et操作時(shí),不準(zhǔn)進(jìn)行set操作 mandName = mandName; cmd.cmdContent = command.cmdContent; cmd.parity = command.parity; cmd.replyContent = command.replyContent; cmd.replyLength = command.replyLength; cmd.isCompleted = command.isCompleted; Monitor.Exit(this); return c
30、md;,public void setCommand(CCommand cmd) Monitor.Enter(this); /線程同步:在進(jìn)行set操作時(shí),不準(zhǔn)進(jìn)行g(shù)et操作 mand = cmd; Monitor.Exit(this); protected virtual bool checkReply(string cmdType, byte bRecv) return false; private void threadFun() SerialPort sp = new SerialPort(portName, baudRate, Parity.None, dataBits, stopB
31、its); try if (sp.IsOpen) sp.Close(); sp.Open();,catch return; byte first; byte bRecv, bSend; while (!stopFlag) CCommand cmd = getCommand(); if (cmd.isCompleted = false) try sp.ReadTimeout = readTimeOut; sp.ReadExisting(); /清除接收緩沖區(qū) bSend = cmd.cmdContent;/要發(fā)送的內(nèi)容 sp.Parity = cmd.parity;/校驗(yàn)位 sp.Write(b
32、Send, 0, bSend.Length); first = (byte)sp.ReadByte(); /阻塞方式讀取數(shù)據(jù),bRecv = new bytecmd.replyLength;/存儲(chǔ)回復(fù)數(shù)據(jù)(字節(jié)數(shù)已經(jīng)規(guī)定) bRecv0 = first; int n = 0;/檢查的次數(shù) while (n 3) continue; /等待3次后數(shù)據(jù)還未到達(dá) sp.Read(bRecv, 1, cmd.replyLength - 1); if (checkReply(mandName, bRecv) cmd.replyContent = bRecv;/填寫回復(fù)內(nèi)容 cmd.isCompleted
33、 = true;/修改命令完成標(biāo)志 setCommand(cmd); if (DataReceived != null) /引發(fā)事件,通知使用該類的程序 DataReceived(this);,catch else Thread.Sleep(20);/沒有新命令下達(dá),延時(shí)防止CPU占用率過高 if (sp != null 在前一個(gè)步驟中已經(jīng)實(shí)現(xiàn)了串口數(shù)據(jù)接收、解析和顯示的功能,并且在工作者線程中接收和處理數(shù)據(jù),在此期間前臺(tái)的UI線程能響應(yīng)用戶輸入。從功能上看,已經(jīng)能夠滿足用戶需求,但是從代碼的組織和管理角度看,該程序還有比較大問題:負(fù)責(zé)接收和處理數(shù)據(jù)的代碼和負(fù)責(zé)顯示的代碼混雜在一起,不能重復(fù)使
34、用,若增加一個(gè)同類設(shè)備,很多代碼還要重寫,而且給查看和調(diào)試程序也帶來較大困難。下面用面向?qū)ο蠓椒▽?duì)程序進(jìn)行重新設(shè)計(jì),3 HC-100智能測(cè)控儀數(shù)據(jù)采集 HC-100智能測(cè)控儀采用以上位機(jī)為主導(dǎo)的“提問應(yīng)答”通信模式,管理該設(shè)備的類可以從CActiveCOMHelper類派生而來,命名為CHC100,在類中覆蓋checkReply方法,并實(shí)現(xiàn)浮點(diǎn)數(shù)的解碼方法AsciiToFloat。該類的實(shí)現(xiàn)代碼如下: public class CHC100 : CActiveCOMHelper public CHC100(string portName, int baudRate, int dataBits,
35、 StopBits stopBits) : base(portName, baudRate, dataBits, stopBits) /根據(jù)命令名稱構(gòu)建命令對(duì)象 public CCommand makeCommand(string commandName) CCommand command = new CCommand(,switch (commandName) case R: /讀數(shù)據(jù)指令 mandName = commandName; command.replyLength = 11; command.cmdContent = new byte 0 x04, 0 x30, 0 x31, 0
36、 x52, 0 x30, 0 x30, 0 x05 ; break; return command; protected override bool checkReply(string cmdType, byte bRecv) switch (cmdType) case R: /讀數(shù)據(jù)指令 if (bRecv0 = 0 x02,return false; public float AsciiToFloat(byte b) StringBuilder s = new StringBuilder(); for (int i = 3; i = 8; i+) /下標(biāo)為3到8的數(shù)據(jù)段表示浮點(diǎn)數(shù)值 s.A
37、ppend(char)bi); /將字符連接為字符串 float f = 0F; try f = Single.Parse(s.ToString(); /字符串轉(zhuǎn)換為浮點(diǎn)數(shù) catch return f;,下面的代碼說明了CHC100類在UI模塊中的應(yīng)用。后臺(tái)工作者線程獲得下位機(jī)應(yīng)答數(shù)據(jù)后,存儲(chǔ)在CCommand對(duì)象中,不用事件通知UI線程。UI線程每隔1秒鐘檢查一次命令執(zhí)行情況,如果命令執(zhí)行完畢,則讀取本次的應(yīng)答數(shù)據(jù),并設(shè)置下一次的命令。 private CHC100 hc100; private void btnStart_Click(object sender, EventArgs e)
38、 /開始采集數(shù)據(jù) hc100 = new CHC100(COM1, 9600, 8, StopBits.One); hc100.start(); timer1.Enabled = true; private void btnStop_Click(object sender, EventArgs e) /結(jié)束采集 timer1.Enabled = false; hc100.stop();,private void timer1_Tick(object sender, EventArgs e) CCommand cmd = hc100.getCommand(); /獲取當(dāng)前命令 if (cmd.i
39、sCompleted) /當(dāng)面命令已完成 CCommand nextCmd = hc100.makeCommand(R); /構(gòu)建下一個(gè)命令 hc100.setCommand(nextCmd); if (cmd.cmdContent != null) Trace.WriteLine(HC100回復(fù):壓力: + AsciiToFloat(cmd.replyContent); else Trace.WriteLine(mandName + 命令還未完成);,4 JW-2A扭矩儀數(shù)據(jù)采集 JW-2A扭矩儀用于測(cè)量鉆機(jī)的扭矩和轉(zhuǎn)速,該設(shè)備和HC-100智能測(cè)控儀相似,也采用以上位機(jī)為主導(dǎo)的“提問應(yīng)答”
40、通信模式,不同的是通信方式比HC-100智能測(cè)控儀稍微復(fù)雜,每次通信需要發(fā)送兩道命令,首先發(fā)尋址指令激活,再發(fā)送讀數(shù)據(jù)指令獲取數(shù)據(jù)。 管理該設(shè)備的類從CActiveCOMHelper類派生而來,命名為CJW2A,代碼如下: class CJW2A : CActiveCOMHelper public CJW2A(string portName, int baudRate, int dataBits, StopBits stopBits) : base(portName, baudRate, dataBits, stopBits) public CCommand makeCommand(strin
41、g commandName) /根據(jù)命令名稱構(gòu)建命令對(duì)象 CCommand command = new CCommand(,switch (commandName) case A: /尋址指令(激活設(shè)備) mandName = commandName; command.replyLength = 1; command.parity = Parity.Mark; command.cmdContent = new byte 0 x0A ; break; case R: /讀數(shù)據(jù)指令 mandName = commandName; command.replyLength = 10; command.
42、parity = Parity.Space; command.cmdContent = new byte 0 x00 ; break; return command;,protected override bool checkReply(string cmdType, byte bRecv) switch (cmdType) case A: /尋址指令 if (bRecv0 = 0 x0A) return true; break; case R: /讀數(shù)據(jù)指令 if (bRecv0 = 0 x02,public float HexToFloat(byte data) /4字節(jié)轉(zhuǎn)換為浮點(diǎn)數(shù)(按照
43、IEEE754規(guī)范) int s; /符號(hào)位,+1或者-1。 int e; /指數(shù),根據(jù)IEEE754,指數(shù)部份算出來后要減127 float m; /小數(shù)位。 float mreturn; /返回的浮點(diǎn)數(shù),應(yīng)為:(1+小數(shù)位)* 2(指數(shù))*(符號(hào)位) s = data0,在UI模塊中,每個(gè)CJW2A對(duì)象負(fù)則和一個(gè)JW-2A扭矩儀通信,由于每次通信過程要發(fā)送兩道命令,所以代碼中采用事件通知方式來使兩道命令連貫地發(fā)送,當(dāng)收到第一道命令的回復(fù)后,引發(fā)事件,在事件處理程序中緊接著發(fā)第二道命令。代碼如下: private CJW2A jw2a; private void btnStart_Click
44、(object sender, EventArgs e) jw2a = new CJW2A(COM3, 4800, 8, StopBits.One); jw2a.DataReceived += new CActiveCOMHelper.DataReceivedHandler(DataReceived); jw2a.start(); timer1.Enabled = true; private void btnStop_Click(object sender, EventArgs e) timer1.Enabled = false; jw2a.stop();,private void DataR
45、eceived(CActiveCOMHelper sender) CCommand cmd, nextCmd; switch (sender.portName.ToUpper() case COM3: /JW2A要先發(fā)“A”命令,完成后緊接著發(fā)“R”命令 cmd = jw2a.getCommand(); if (mandName = A /處理JW2A的返回結(jié)果,cmd = jw2a.getCommand(); if (mandName = R,5 LU-902M位式調(diào)節(jié)儀數(shù)據(jù)采集 LU-902M位式調(diào)節(jié)儀在鉆機(jī)性能測(cè)試系統(tǒng)中應(yīng)用最廣泛,用于測(cè)量大氣溫度、馬達(dá)溫度、泵溫度、油溫、冷卻水流量、馬
46、達(dá)進(jìn)油流量、馬達(dá)回油流量、馬達(dá)油壓、操縱臺(tái)噪音、馬達(dá)噪音等諸多參數(shù),該設(shè)備同樣采用以上位機(jī)為主導(dǎo)的“提問應(yīng)答”通信模式,它仍然需要激活,不過只激活一次,以后就象HC-100智能測(cè)控儀一樣發(fā)送查詢指令獲取數(shù)據(jù)。 管理該設(shè)備的類從CActiveCOMHelper類派生而來,命名為CLU902M,代碼如下: class CLU902M : CActiveCOMHelper public bool isActive; /設(shè)備激活標(biāo)志 public byte address; /設(shè)備地址 public CLU902M(string portName, int baudRate, int dataBits
47、, StopBits stopBits) : base(portName, baudRate, dataBits, stopBits) /根據(jù)命令名稱構(gòu)建命令對(duì)象,public CCommand makeCommand(string commandName) CCommand command = new CCommand(); switch (commandName) case A: /尋址指令(激活設(shè)備) mandName = commandName; command.replyLength = 2; command.parity = Parity.Mark; command.cmdCont
48、ent = new byte address ; break; case R: /讀數(shù)據(jù)指令 mandName = commandName; command.replyLength = 8; command.parity = Parity.Space; command.cmdContent = new byte 0 x45 ; break; return command;,protected override bool checkReply(string cmdType, byte bRecv) switch (cmdType) case A: /尋址命令 if (bRecv0 = 0 x4F,public float HexToFloat(byte H, byte L
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 電子商務(wù)+物流配送項(xiàng)目投資合同
- 房地產(chǎn)經(jīng)紀(jì)行業(yè)二手房買賣中介服務(wù)合同
- 電子競(jìng)技產(chǎn)業(yè)投資開發(fā)合同
- 新版勞務(wù)分包合同
- 古董買賣合同買賣協(xié)議
- 二零二五年度電子廢物處理與資源化利用合同3篇
- 二零二四年度云計(jì)算服務(wù)數(shù)字化加工保密合同3篇
- 二零二四年度養(yǎng)老服務(wù)業(yè)會(huì)計(jì)人員聘用合同協(xié)議3篇
- 二零二四年度企業(yè)師帶徒市場(chǎng)營(yíng)銷合作合同3篇
- 二零二四年度專業(yè)協(xié)議離婚書模板與婚姻解除后子女撫養(yǎng)權(quán)代理合同3篇
- 2018注冊(cè)環(huán)保工程師考試公共基礎(chǔ)真題及答案
- 勞務(wù)經(jīng)紀(jì)人培訓(xùn)
- 如何提高售后服務(wù)的快速響應(yīng)能力
- 成人氧氣吸入療法-中華護(hù)理學(xué)會(huì)團(tuán)體標(biāo)準(zhǔn)
- ?;愤\(yùn)輸安全緊急救援與處理
- Unit-3-Reading-and-thinking課文詳解課件-高中英語(yǔ)人教版必修第二冊(cè)
- 高數(shù)(大一上)期末試題及答案
- 婚介公司紅娘管理制度
- 煤礦電氣試驗(yàn)規(guī)程
- 物業(yè)客服培訓(xùn)課件PPT模板
- 火力發(fā)電廠節(jié)能管理制度實(shí)施細(xì)則
評(píng)論
0/150
提交評(píng)論