多個串口設(shè)備數(shù)據(jù)的連續(xù)采集.ppt_第1頁
多個串口設(shè)備數(shù)據(jù)的連續(xù)采集.ppt_第2頁
多個串口設(shè)備數(shù)據(jù)的連續(xù)采集.ppt_第3頁
多個串口設(shè)備數(shù)據(jù)的連續(xù)采集.ppt_第4頁
多個串口設(shè)備數(shù)據(jù)的連續(xù)采集.ppt_第5頁
已閱讀5頁,還剩46頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

工控程序設(shè)計,學(xué)習(xí)情景2.4 多個串口設(shè)備數(shù)據(jù)的連續(xù)采集,學(xué)習(xí)情景2.4 多個串口設(shè)備數(shù)據(jù)的連續(xù)采集,2.4.1 學(xué)習(xí)要點 1.知識點: 煤礦鉆機性能檢測設(shè)備的數(shù)據(jù)通信協(xié)議,數(shù)據(jù)幀的校驗方法 2.技能點: 校驗碼的計算,上位機主動模式串口通信類的設(shè)計,HC-100智能測控儀、JW-2A扭矩儀、LU-902M位式調(diào)節(jié)儀數(shù)據(jù)采集 2.4.2 任務(wù)描述 在前一個情景中實現(xiàn)了對單個HSDZC電能綜合測試數(shù)據(jù)的接收。在鉆機性能測試系統(tǒng)中,還需要使用JW-2A扭矩儀、HC-100智能測控儀、LU-902M位式調(diào)節(jié)儀來采集其它參數(shù)的值,而這些設(shè)備的數(shù)據(jù)通信規(guī)則不同,所以必須對每種設(shè)備編寫通信程序,并同步、連續(xù)地采集多個設(shè)備的數(shù)據(jù)。 該教學(xué)情景中先針對上位機主動通信模式設(shè)計基類CActiveCOMHelper,再分別對三種不同的儀器分別設(shè)計派生類來進行數(shù)據(jù)管理,實現(xiàn)對多個不同設(shè)備進行同步、連續(xù)的數(shù)據(jù)采集。,2.4.3 相關(guān)知識 1 煤礦鉆機性能檢測設(shè)備的數(shù)據(jù)通信協(xié)議 (1) HC-100智能測控儀 HC-100智能測控儀可以使用RS232、RS485接口與計算機通訊,數(shù)據(jù)格式為1個起始位,8個數(shù)據(jù)位,無奇偶校驗,1個停止位,共11位。設(shè)備的所有數(shù)字變換成ASCII碼進行傳輸:例如:儀表編號Addr=01,測量值=123.4,則數(shù)據(jù)千位為31H、百位為32H、十位為33H、小數(shù)點為2EH,個位為34H,符號位2BH為正,2DH為負。 從儀表讀數(shù)據(jù)的指令格式為:EOT+儀表地址編號+52H+參數(shù)+ENQ 表2.4.1 發(fā)送給HC100的數(shù)據(jù)格式,儀表返回數(shù)據(jù)的格式為:STX+儀表地址編號+符號位+測量值+校驗碼+ETX。其中的數(shù)據(jù)參數(shù)值為符號位+4位有效位+小數(shù)點,共6位,校驗碼為前面發(fā)送的9個字節(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扭矩儀采用多機通訊方式,本機地址為0AH。數(shù)據(jù)位8位,停止位1位。波特率可用跳線選擇4800bps或2400bps。奇偶位在這里做地址和數(shù)據(jù)判別位,1為地址,0為數(shù)據(jù)。儀器只被地址觸發(fā),即上位機只有向儀器發(fā)0AH,并且奇偶位為1時,才能得到儀器的響應(yīng)。儀器被本機地址觸發(fā)后,向上位機傳回本機地址,然后等待上位機發(fā)來的命令。受到命令后,根據(jù)命令執(zhí)行不同的任務(wù)。命令為一個字節(jié)。目前有效的命令有15個,下面敘述各命令代表的任務(wù)。 0:讀扭矩轉(zhuǎn)速 儀器受到命令后向上位機依次傳送扭矩,轉(zhuǎn)速,采樣時間3個參數(shù)。扭矩、轉(zhuǎn)速為浮點數(shù),每個參數(shù)4個字節(jié)。采樣時間為整數(shù),2個字節(jié)。每個參數(shù)的傳送順序都是從內(nèi)存的低地址到高地址 1:存儲操作。在測量狀態(tài)收到此命令,將啟動存儲操作;在存儲狀態(tài)收到此命令,將退出存儲狀態(tài)。 2:讀儀器存儲的數(shù)據(jù)數(shù)組。在非存儲狀態(tài)收到此命令,將向上位機傳送春初數(shù)據(jù)的數(shù)組。 3:釋放操作。在測量狀態(tài)收到此命令,將啟動釋放操作;在釋放狀態(tài)儀器不再接受命令。,4:扣除/不扣除轉(zhuǎn)換。在扣除狀態(tài)收到此命令,將退出扣除狀態(tài);在非扣除狀態(tài)收到此命令,將進入扣除狀態(tài)。 5:內(nèi)/外轉(zhuǎn)速顯示轉(zhuǎn)換。在顯示內(nèi)轉(zhuǎn)速時收到此命令,將顯示外轉(zhuǎn)速;在顯示外轉(zhuǎn)速時收到此命令,將顯示內(nèi)轉(zhuǎn)速。 6:調(diào)零操作。儀器才測量狀態(tài)收到此命令,將啟動調(diào)零操作。 7:讀儀器狀態(tài)。儀器收到命令后向上位機 傳送儀器狀態(tài)字節(jié)。狀態(tài)字節(jié)各位的定義如表2.4.3所示。 表2.4.3 JW-2A通信協(xié)議,8:讀模擬通道數(shù)據(jù)。儀器收到命令后向上位機依次傳送0至7通道的A/D采樣結(jié)果。每通道2字節(jié),高位在前。低14位表示數(shù)值大小,最高2位表示小數(shù)點位置。小數(shù)點位置為0,有0位小數(shù)點;小數(shù)點位置為1,有1位小數(shù)點;小數(shù)點位置為2,有2位小數(shù)點。 9:讀0點。儀器收到命令后向上位機依次傳送10個零點值和其相應(yīng)的轉(zhuǎn)速值。每個零點6個字節(jié)(前4個字節(jié)是零點,浮點數(shù),后2個字節(jié)是轉(zhuǎn)速,無符號整數(shù),高位在前),共60個字節(jié)。 10:寫零點。儀器受到命令后準備接受10個零點,共60個字節(jié)的數(shù)據(jù)。上位機應(yīng)按上述讀零點的順序依次將60個字節(jié)寫回去。注意,寫零點不能少于60字節(jié)。 11:讀扭矩參數(shù)。儀器收到命令后向上位機依次傳送11個參數(shù),共24個字節(jié)。這11個參數(shù)的排列順序,數(shù)據(jù)類型,數(shù)據(jù)長度如表2.4.4所示。 12:寫扭矩參數(shù)。儀器收到命令后準備接受11個參數(shù),共24個字節(jié)的數(shù)據(jù)。上位機應(yīng)按上述讀扭矩參數(shù)的順序依次將24個字節(jié)寫回去。注意:寫扭矩參數(shù)不能少于24字節(jié)。 13:讀模擬通道量程。儀器收到命令后向上位機依次傳送8個通道的量程值。每個量程2個字節(jié),共16個字節(jié)。數(shù)據(jù)類型是無符號整數(shù),高位在前。低14位表示數(shù)值大小,最高2位表示小數(shù)點位置。小數(shù)點位置為0,有0位小數(shù)點;小數(shù)點位置為1,有1位小數(shù)點,小數(shù)點位置為2,有2位小數(shù)點。,表2.4.4 JW-2A的扭矩參數(shù),14:寫模擬通道量程。儀器收到命令后準備接收8個通道的量程表。每個量程2個字節(jié),共16個字節(jié)。數(shù)據(jù)類型是無符號整數(shù),高位在前。低14位表示數(shù)值大小,最高2位表示小數(shù)點位置。小數(shù)點位置為0,有0位小數(shù)點;小數(shù)點位置為1,有1位小數(shù)點,小數(shù)點位置為2,有2位小數(shù)點。上位機應(yīng)按上述讀模擬通道量程的順序依次將16個字節(jié)寫回去。需要注意的是:寫模擬通道量程不能少于16字節(jié)。,JW-2A扭矩儀的數(shù)據(jù)采用IEEE浮點數(shù)形式表示,需要作浮點數(shù)字節(jié)數(shù)組到浮點數(shù)的轉(zhuǎn)換。如果用DCBA表示浮點數(shù),D為高位,A為低位,每個字母表示一個字節(jié),那么DCBA依次為 SXXX XXXX XMMM MMMM MMMM MMMM MMMM MMMM,其中S代表符號,1位,1表示負,0表示正,X代表指數(shù),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ù)據(jù)都會將數(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個起始位(第0位),8個數(shù)據(jù)位(第1-8位),1個“尋址/數(shù)據(jù)”選擇位(第9位,決定指令類別),1個停止位,共11位,數(shù)據(jù)采用16進制表達。在每個通訊指令中,儀表最后返回信息4FH、4BH表示通訊成功,返回3FH,3FH表示通訊失敗。 1)尋址指令 當上位機要對某LU-902M儀表進行通訊操作時,應(yīng)先對其發(fā)尋址指令。尋址指令為單字節(jié)指令,第1-8位為地址,第9位(校驗位)為“1”(非尋址指令為“0”)。 2)數(shù)據(jù)讀取指令 指令格式:45H 儀表返回:PV、SV、MV、4FH、4BH 其中PV為測量值、SV為設(shè)定值、MV為輸出值,各占兩個字節(jié),低字節(jié)在前高字節(jié)在后。 3)讀參數(shù)指令 指令格式:52H + 參數(shù)代碼 儀表返回:參數(shù)值 + 4FH、4BH 4)寫參數(shù)指令 指令格式:57H + 參數(shù)代碼 + 參數(shù)值 儀表返回:4FH、4BH 5)結(jié)束指令 指令格式:4FH或第9位為“1”的非本機尋址指令 儀表無返回,2 數(shù)據(jù)幀的校驗 數(shù)據(jù)幀校驗的目的是為了檢查接收到的數(shù)據(jù)幀的完整性和準確性。和校驗位不同,校驗位的作用是保證一個數(shù)據(jù)單位的正確性,是從微觀角度考慮。形象地說,校驗位保證一個字正確,數(shù)據(jù)幀校驗是保證一段話正確。 對數(shù)據(jù)幀進行校驗的方法是:發(fā)送方根據(jù)要發(fā)送的數(shù)據(jù)幀,利用某種算法計算出若干字節(jié)的校驗碼,并把校驗碼附加在數(shù)據(jù)幀中發(fā)送給接收端,接收端接收到數(shù)據(jù)后,分離出校驗碼和數(shù)據(jù)本身,再根據(jù)發(fā)送方的算法,計算出校驗碼,如果和接收到的校驗碼一致,則認為接收到的數(shù)據(jù)準確無誤。串口通信中常用的校驗方式有累加和校驗、異或和校驗、循環(huán)冗余校驗等。 (1)累加和校驗 累加和校驗的過程是,發(fā)送端將數(shù)據(jù)的每個字節(jié)累加求和,然后截取最低字節(jié)(或最低兩字節(jié))作為校驗碼發(fā)送給接收端,接收端收到數(shù)據(jù)后,用同樣的方法計算累加和,并與發(fā)送過來的校驗碼進行比較,從而檢驗發(fā)送的數(shù)據(jù)是否有誤。 (2)異或和校驗 異或和校驗的過程是,發(fā)送端取出發(fā)送數(shù)據(jù)的第1個字節(jié),與后續(xù)每個字節(jié)依次按位異或,然后將計算結(jié)果(1個字節(jié))作為校驗碼發(fā)送給接收端,接收端收到數(shù)據(jù)后,用同樣的方法計算異或和,并與發(fā)送過來的校驗碼進行比較,從而檢驗發(fā)送的數(shù)據(jù)是否有誤。,(3)循環(huán)冗余校驗 循環(huán)冗余校驗(Cyclical Redundancy Check)簡稱CRC,它利用除法及余數(shù)的原理來作錯誤偵測。實際應(yīng)用時,發(fā)送端計算出校驗碼值并附加在數(shù)據(jù)幀中發(fā)送給接收端,接收端對收到的數(shù)據(jù)重新計算校驗碼并與收到的校驗碼相比較,若兩個值不同,則說明數(shù)據(jù)通訊出現(xiàn)錯誤,要求發(fā)送端重新發(fā)送。 常用的CRC標準有CRC-12、CRC-16、CRC-CCITT和CRC-32,其中CRC-16和CRC-CCITT用來作一個字節(jié)數(shù)據(jù)的校驗,在串口數(shù)據(jù)校驗中最常用的是CRC-16。下面是循環(huán)冗余校驗碼的計算過程: 1)設(shè)置CRC寄存器,并給其賦值FFFF(hex)。 2)將數(shù)據(jù)的第一個字節(jié)與16位CRC寄存器的低8位進行異或,并把結(jié)果存入CRC寄存器。 3)CRC寄存器向右移一位,MSB(最高有效位)補零,移出并檢查LSB(最低有效位)。 4)如果LSB為0,重復(fù)第三步;若LSB為1,CRC寄存器與多項式碼相異或。 5)重復(fù)第3與第4步直到8次移位全部完成。此時一個字節(jié)數(shù)據(jù)處理完畢。 6)重復(fù)第2至第5步直到所有數(shù)據(jù)全部處理完成。 7)最終CRC寄存器的內(nèi)容即為CRC值。 常用的循環(huán)冗余校驗標準多項式為: 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多項式對應(yīng)多項式碼為1000 0000 0000 0101(0x8005),CRC-CCITT對應(yīng)的多項式碼為0001 0000 0010 0001(0x1021)。,2.4.4 任務(wù)實施 1 校驗碼的計算 在串口通信通,校驗碼在保證數(shù)據(jù)幀的正確性方面具有重要作用,雖然在鉆機性能測試系統(tǒng)中只用到累加和校驗,但為了能應(yīng)對串口通信中可能出現(xiàn)的復(fù)雜情況,下面對三種校驗碼的計算都進行具體實現(xiàn)。 (1)累加和校驗碼的計算 累加和校驗碼可以取累加和的低8位(1個字節(jié))或低16位(兩個字節(jié)),在下位機處理能力允許的情況下采用兩個字節(jié)作校驗碼可以提高校驗的準確度。 下面的C#代碼將累加和校驗碼生成功能封裝到CCheck類的方法中,其中CheckSum_1方法計算單字節(jié)累加和校驗碼,CheckSum_2方法計算雙字節(jié)累加和校驗碼 class CCheck /函數(shù)功能: /計算字節(jié)數(shù)組b中從offset位置開始的count個元素的單字節(jié)累加和校驗碼 /參數(shù): /b:要計算累加和的字節(jié)數(shù)組 /offset:要計算累加和的元素的起始位置 /count:要計算累加和的連續(xù)元素個數(shù) /返回值:累加和的低8位(單個字節(jié)),public static byte CheckSum_1(byte b, int offset, int count) uint sum = 0; for (int i = offset; i offset + count; i+) sum += bi; /數(shù)組元素累加求和 return (byte)(sum /函數(shù)功能: /計算字節(jié)數(shù)組b中從offset位置開始的count個元素的雙字節(jié)累加和校驗碼 /參數(shù): /b:要計算累加和的字節(jié)數(shù)組 /offset:要計算累加和的元素的起始位置 /count:要計算累加和的連續(xù)元素個數(shù) /返回值:長度為2的字節(jié)數(shù)組,第1個元素為累加和的低8位 /第2個元素為累加和的高8位,public static byte CheckSum_2(byte b, int offset, int count) uint sum = 0; byte tmp = new byte2; /存放累加和的低8位和高8位 for (int i = offset; i 8); /高8位在后 return tmp; 下面的測試程序調(diào)用CheckSum_1方法,計算出長度為1個字節(jié)的累加和校驗碼,并附加在字節(jié)數(shù)組末尾: byte b =0x41,0x42,0x43,0; /保留一個字節(jié)位置存儲校驗碼 byte sum = CCheck.CheckSum_1(b, 0, b.Length - 1); /計算單字節(jié)累加和 bb.Length-1 = sum; /附加在字節(jié)數(shù)組末尾,下面的測試程序調(diào)用CheckSum_2方法,計算出長度為兩個字節(jié)的累加和校驗碼,并附加在字節(jié)數(shù)組末尾: byte b =0x41,0x42,0x43,0,0; /保留兩個字節(jié)位置存儲校驗碼 byte sum = CCheck.CheckSum_2(b, 0, b.Length - 2); /計算雙字節(jié)累加和 bb.Length-2 = sum0; /附加在字節(jié)數(shù)組末尾 bb.Length-1 = sum1; (2)異或和校驗碼的計算 下面的C#代碼將異或和校驗碼生成功能封裝到CCheck類的方法中,方法名為XorSum: class CCheck /函數(shù)功能: /計算字節(jié)數(shù)組b中從offset位置開始的count個元素的單字節(jié)異或和校驗碼 /參數(shù): /b:要計算累加和的字節(jié)數(shù)組 /offset:要參與計算校驗碼的元素的起始位置 /count:要參與計算校驗碼的連續(xù)元素個數(shù) /返回值:異或和(8位,1個字節(jié)),public static byte XorSum(byte b, int offset, int count) byte sum = 0; for (int i = offset; i offset + count; i+) sum = bi; /依次和每個元素進行按位異或運算 return sum; 下面的測試程序調(diào)用XorSum方法,計算出長度為1個字節(jié)的異或和校驗碼,并附加在字節(jié)數(shù)組末尾: byte b =0x41,0x42,0x43,0; /保留一個字節(jié)位置存儲校驗碼 byte xorsum = CCheck. XorSum(b, 0, b.Length - 1); /計算異或和 bb.Length-1 = xorsum; /附加在字節(jié)數(shù)組末尾,(3)循環(huán)冗余校驗碼的計算 下面的C#代碼將CRC-16校驗碼生成功能封裝到CCheck類的方法中,方法名為CRC16: class CCheck /函數(shù)功能: /計算字節(jié)數(shù)組b中從offset位置開始的count個元素的循環(huán)冗余校驗碼 /參數(shù): /b:要計算累加和的字節(jié)數(shù)組 /offset:要參與計算校驗碼的元素的起始位置 /count:要參與計算校驗碼的連續(xù)元素個數(shù) / CrcPoly:CRC多項式對應(yīng)的16位二進制編碼 /返回值:長度為2的字節(jié)數(shù)組,第1個元素為校驗碼的低8位 /第2個元素為校驗碼的高8位,public static byte CRC16(byte b, int offset, int count, ushort CrcPoly) ushort CrcReg = 0xFFFF; /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 上位機主動模式串口通信類的設(shè)計 煤礦鉆機性能測試系統(tǒng)中用到的HC-100智能測控儀、JW-2A扭矩儀和LU-902M位式調(diào)節(jié)儀與HSDZC電能綜合測試儀不同,這些設(shè)備需要上位機主動發(fā)送命令,才給予回復(fù),因此可以把這三種設(shè)備的通信模式歸為“上位機主動模式”。 下面將設(shè)計上位機主動模式的串口通信類CActiveCOMHelper,和CPassiveCOMHelper類不同的是,CActiveCOMHelper類中增加了一個名為command的成員,存放當前應(yīng)該執(zhí)行的命令,線程函數(shù)根據(jù)該成員的相關(guān)屬性,就知道現(xiàn)在應(yīng)該給下位機發(fā)送什么命令。由于采用“提問回答”的方式,能夠準確控制下位機發(fā)送來的數(shù)據(jù),故不再需要隊列來暫存接收的數(shù)據(jù)。 CCommand類實現(xiàn)代碼如下: public class CCommand public string commandName;/命令名字 public byte cmdContent;/命令的內(nèi)容 public Parity parity = Parity.None;/發(fā)送命令時采用的校驗方式 public byte replyContent;/回復(fù)內(nèi)容,public int replyLength;/回復(fù)內(nèi)容的規(guī)定長度 public bool isCompleted; /命令是否完成 public CCommand() /創(chuàng)建對象時commandName不能為null,以免后面比較時出錯 mandName = “; command成員(CCommand的實例)是UI模塊和CActiveCOMHelper對象的連接紐帶。UI模塊首先查詢前一個命令是否完成(isCompleted是否為true),若已經(jīng)完成,就設(shè)置下一條命令的名字、內(nèi)容、校驗方式、回復(fù)內(nèi)容的規(guī)定長度,交給CActiveCOMHelper對象去執(zhí)行;CActiveCOMHelper對象執(zhí)行完命令后,把回復(fù)內(nèi)容填好,并將完成標志isCompleted設(shè)置為true。如此循環(huán),就可以不斷讓CActiveCOMHelper對象執(zhí)行命令。這樣分工的好處是,處于上層的UI模塊沒有必要知道如何和串口通信、如何創(chuàng)建線程等等復(fù)雜瑣碎的具體操作,而只要知道該發(fā)什么命令,以及如何處理收到的結(jié)果。,CActiveCOMHelper類實現(xiàn)代碼如下: public class CActiveCOMHelper public int readTimeOut;/接收數(shù)據(jù)超時毫秒數(shù) public string portName;/設(shè)備所占用的串口名 private bool stopFlag;/線程循環(huán)停止標志 private int baudRate, dataBits; private StopBits stopBits; private CCommand command; public delegate void DataReceivedHandler(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;/默認3000毫秒讀取超時 mand = new CCommand(); /始終保持有一個命令 mand.isCompleted = true; /該命令開始時處于完成狀態(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() /獲取一個克隆的命令對象 CCommand cmd = new CCommand(); Monitor.Enter(this); /線程同步:在進行g(shù)et操作時,不準進行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 cmd; ,public void setCommand(CCommand cmd) Monitor.Enter(this); /線程同步:在進行set操作時,不準進行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, stopBits); 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;/校驗位 sp.Write(bSend, 0, bSend.Length); first = (byte)sp.ReadByte(); /阻塞方式讀取數(shù)據(jù),bRecv = new bytecmd.replyLength;/存儲回復(fù)數(shù)據(jù)(字節(jié)數(shù)已經(jīng)規(guī)定) bRecv0 = first; int n = 0;/檢查的次數(shù) while (n 3) continue; /等待3次后數(shù)據(jù)還未到達 sp.Read(bRecv, 1, cmd.replyLength - 1); if (checkReply(mandName, bRecv) cmd.replyContent = bRecv;/填寫回復(fù)內(nèi)容 cmd.isCompleted = true;/修改命令完成標志 setCommand(cmd); if (DataReceived != null) /引發(fā)事件,通知使用該類的程序 DataReceived(this); ,catch else Thread.Sleep(20);/沒有新命令下達,延時防止CPU占用率過高 if (sp != null 在前一個步驟中已經(jīng)實現(xiàn)了串口數(shù)據(jù)接收、解析和顯示的功能,并且在工作者線程中接收和處理數(shù)據(jù),在此期間前臺的UI線程能響應(yīng)用戶輸入。從功能上看,已經(jīng)能夠滿足用戶需求,但是從代碼的組織和管理角度看,該程序還有比較大問題:負責(zé)接收和處理數(shù)據(jù)的代碼和負責(zé)顯示的代碼混雜在一起,不能重復(fù)使用,若增加一個同類設(shè)備,很多代碼還要重寫,而且給查看和調(diào)試程序也帶來較大困難。下面用面向?qū)ο蠓椒▽Τ绦蜻M行重新設(shè)計。,3 HC-100智能測控儀數(shù)據(jù)采集 HC-100智能測控儀采用以上位機為主導(dǎo)的“提問應(yīng)答”通信模式,管理該設(shè)備的類可以從CActiveCOMHelper類派生而來,命名為CHC100,在類中覆蓋checkReply方法,并實現(xiàn)浮點數(shù)的解碼方法AsciiToFloat。該類的實現(xiàn)代碼如下: public class CHC100 : CActiveCOMHelper public CHC100(string portName, int baudRate, int dataBits, StopBits stopBits) : base(portName, baudRate, dataBits, stopBits) /根據(jù)命令名稱構(gòu)建命令對象 public CCommand makeCommand(string commandName) CCommand command = new CCommand();,switch (commandName) case “R“: /讀數(shù)據(jù)指令 mandName = commandName; command.replyLength = 11; command.cmdContent = new byte 0x04, 0x30, 0x31, 0x52, 0x30, 0x30, 0x05 ; break; return command; protected override bool checkReply(string cmdType, byte bRecv) switch (cmdType) case “R“: /讀數(shù)據(jù)指令 if (bRecv0 = 0x02 ,return false; public float AsciiToFloat(byte b) StringBuilder s = new StringBuilder(); for (int i = 3; i = 8; i+) /下標為3到8的數(shù)據(jù)段表示浮點數(shù)值 s.Append(char)bi); /將字符連接為字符串 float f = 0F; try f = Single.Parse(s.ToString(); /字符串轉(zhuǎn)換為浮點數(shù) catch return f; ,下面的代碼說明了CHC100類在UI模塊中的應(yīng)用。后臺工作者線程獲得下位機應(yīng)答數(shù)據(jù)后,存儲在CCommand對象中,不用事件通知UI線程。UI線程每隔1秒鐘檢查一次命令執(zhí)行情況,如果命令執(zhí)行完畢,則讀取本次的應(yīng)答數(shù)據(jù),并設(shè)置下一次的命令。 private CHC100 hc100; private void btnStart_Click(object sender, EventArgs e) /開始采集數(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(); /獲取當前命令 if (cmd.isCompleted) /當面命令已完成 CCommand nextCmd = hc100.makeCommand(“R“); /構(gòu)建下一個命令 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扭矩儀用于測量鉆機的扭矩和轉(zhuǎn)速,該設(shè)備和HC-100智能測控儀相似,也采用以上位機為主導(dǎo)的“提問應(yīng)答”通信模式,不同的是通信方式比HC-100智能測控儀稍微復(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(string commandName) /根據(jù)命令名稱構(gòu)建命令對象 CCommand command = new CCommand();,switch (commandName) case “A“: /尋址指令(激活設(shè)備) mandName = commandName; command.replyLength = 1; command.parity = Parity.Mark; command.cmdContent = new byte 0x0A ; break; case “R“: /讀數(shù)據(jù)指令 mandName = commandName; command.replyLength = 10; command.parity = Parity.Space; command.cmdContent = new byte 0x00 ; break; return command; ,protected override bool checkReply(string cmdType, byte bRecv) switch (cmdType) case “A“: /尋址指令 if (bRecv0 = 0x0A) return true; break; case “R“: /讀數(shù)據(jù)指令 if (bRecv0 = 0x02 ,public float HexToFloat(byte data) /4字節(jié)轉(zhuǎn)換為浮點數(shù)(按照IEEE754規(guī)范) int s; /符號位,+1或者-1。 int e; /指數(shù),根據(jù)IEEE754,指數(shù)部份算出來后要減127 float m; /小數(shù)位。 float mreturn; /返回的浮點數(shù),應(yīng)為:(1+小數(shù)位)* 2(指數(shù))*(符號位) s = data0 ,在UI模塊中,每個CJW2A對象負則和一個JW-2A扭矩儀通信,由于每次通信過程要發(fā)送兩道命令,所以代碼中采用事件通知方式來使兩道命令連貫地發(fā)送,當收到第一道命令的回復(fù)后,引發(fā)事件,在事件處理程序中緊接著發(fā)第二道命令。代碼如下: private CJW2A jw2a; private void btnStart_Click(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 DataReceived(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é)儀在鉆機性能測試系統(tǒng)中應(yīng)用最廣泛,用于測量大氣溫度、馬達溫度、泵溫度、油溫、冷卻水流量、馬達進油流量、馬達回油流量、馬達油壓、操縱臺噪音、馬達噪音等諸多參數(shù),該設(shè)備同樣采用以上位機為主導(dǎo)的“提問應(yīng)答”通信模式,它仍然需要激活,不過只激活一次,以后就象HC-100智能測控儀一樣發(fā)送查詢指令獲取數(shù)據(jù)。 管理該設(shè)備的類從CActiveCOMHelper類派生而來,命名為CLU902M,代碼如下: class CLU902M : CActiveCOMHelper public bool isActive; /設(shè)備激活標志 public byte address; /設(shè)備地址 public CLU902M(string portName, int baudRate, int dataBits, StopBits stopBits) : base(portName, baudRate, dataBits, stopBits) /根據(jù)命令名稱構(gòu)建命令對象,public CCommand makeCommand(string commandName) CCommand command = new CCommand(); switch (commandName) case “A“: /尋址指令(激活設(shè)備) mandName = commandName; command.replyLength = 2; command.parity = Parity.Mark; command.cmdContent = new byte address ; break; case “R“: /讀數(shù)據(jù)指令 mandName = commandName; command.replyLength = 8; command.parity = Parity.Space; command.cmdContent = new byte 0x45 ; break; return command; ,protected override bool checkReply(string cmdType, byte bRecv) switch (cmdType) case “A“: /尋址命令 if (bRecv0 = 0x4F ,public float HexToFloat(byte H, byte L) return (float)(H *

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論