遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题
http://www.delphi2007.net/DelphiNetwork/html/delphi_20061129164355231.html
Usb芯片:Ch375 ?
? 協議:Modbus ?
? 上位機開發軟件:delphi ?
? 傳輸格式(RTU): ?
? 幀定義: ?
? 頭|命令|長度|數據(高) ? ? ? ---- ? ? ? ? ? 數據(低)|CRC ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? C0C1C2 ? S0S1S2 ? T10T11 ? T20T21 ? P0P1 ?
? 01 ? ? 02 ? ? ? 0C ? ? 000000 ? 000000 ? ? 0000 ? ? ? 0000 ? ? 0000 ? ? XX ?
? ?
? 第一次做這種軟件,還沒有在下位機上測試,先貼出部分源碼,請大家幫忙改正。 ?
? 還有對于從下位機取出來的數據(已從16進制轉換成10進制)有幾個疑問: ?
? 1。是不是就代表了真實的值,是否還需要再轉換; ?
? 2。如何處理浮點型數據。 ?
? 下面是部分源碼:
//讀數據 ?
? function ? ReadData(iIndex:Integer;var ? oBuffer:PChar;var ? ioLength:Integer):Boolean; ?
? ? ? stdcall; ? external ? DllFile ? name ? 'CH375ReadData'; ?
? ?
? function ? TPublicFun.GetData:Integer; ?
? var ?
? ? ? Buff_HAdd ? ? : ? Byte;//幀:頭地址 ?
? ? ? Buff_Cmd ? ? ? : ? Byte;//幀:命令 ?
? ? ? Buff_Len ? ? ? : ? Byte;//幀:長度 ?
? ?
? ? ? Buff_DatLC ? : ? array[1..3] ? of ? Byte;//幀:LC數據 ?
? ? ? Buff_DatLS ? : ? array[1..3] ? of ? Byte;//幀:LS數據 ?
? ?
? ? ? Buff_DatT1 ? : ? array[1..2] ? of ? Byte;//幀:T1數據 ?
? ? ? Buff_DatT2 ? : ? array[1..2] ? of ? Byte;//幀:T2數據 ?
? ? ? Buff_DatP ? ? : ? array[1..2] ? of ? Byte;//幀:P數據 ?
? ? ? ?
? ? ? Buff_Send ? ? : ? array ? of ? Byte;//用于存放各個域合成的總的串 ?
? ? ? I,BuffLen,TempLen ? ? : ? Integer;//傳輸的實際數據長度 ?
? ? ? TempStr,CSort ? ? ? ? : ? string;//用于存放string類型的測試傳輸幀 ?
? ? ? Rtl ? ? ? ? ? ? ? ? : ? Boolean; ?
? ? ? PChar_Send ? : ? PChar; ?
? begin ?
? ? ? Result ? ? ? ? ? := ? -1; ?
? ?
? ? ? //測試用,假設Usb設備已打開 ?
? ? ? Usb_Opened ? := ? True; ?
? ?
? ? ? if ? Usb_Opened ? then ?
? ? ? ? ? begin ?
? ? ? ? ? ? ? //設置頭地址 ?
? ? ? ? ? ? ? Buff_HAdd ? ? := ? HeadCode; ?
? ? ? ? ? ? ? //設置命令 ?
? ? ? ? ? ? ? Buff_Cmd ? ? ? := ? StatusCode; ?
? ?
? ? ? ? ? ? ? //設置長度 ?
? ? ? ? ? ? ? Buff_Len ? ? ? := ? strtohex1(IntToHex(17,2),2); ?
? ? ? ? ? ? ? TempLen ? ? ? ? := ? 17; ?
? ?
? ? ? ? ? ? ? ? ? //初始化LC,LS ?
? ? ? ? ? ? ? ? ? for ? I:=1 ? to ? 3 ? do ?
? ? ? ? ? ? ? ? ? ? ? begin ?
? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatLC[I] ? := ? $00; ?
? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatLS[I] ? := ? $00; ?
? ? ? ? ? ? ? ? ? ? ? end; ?
? ? ? ? ? ? ? ? ? //初始化T,P ?
? ? ? ? ? ? ? ? ? for ? I:=1 ? to ? 2 ? do ?
? ? ? ? ? ? ? ? ? ? ? begin ?
? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatT1[I] ? := ? $00; ?
? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatT2[I] ? := ? $00; ?
? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatP[I] ? ? := ? $00; ?
? ? ? ? ? ? ? ? ? ? ? end; ?
? ?
? ? ? ? ? ? ? SetLength(Buff_Send,TempLen); ?
? ? ? ? ? ? ? //設置總串 ?
? ? ? ? ? ? ? Buff_Send[1] ? := ? Buff_HAdd; ?
? ? ? ? ? ? ? Buff_Send[2] ? := ? Buff_Cmd; ?
? ? ? ? ? ? ? Buff_Send[3] ? := ? Buff_Len; ?
? ?
? ? ? ? ? ? ? Buff_Send[4] ? := ? Buff_DatLC[1]; ?
? ? ? ? ? ? ? Buff_Send[5] ? := ? Buff_DatLC[2]; ?
? ? ? ? ? ? ? Buff_Send[6] ? := ? Buff_DatLC[3]; ?
? ?
? ? ? ? ? ? ? Buff_Send[7] ? := ? Buff_DatLS[1]; ?
? ? ? ? ? ? ? Buff_Send[8] ? := ? Buff_DatLS[2]; ?
? ? ? ? ? ? ? Buff_Send[9] ? := ? Buff_DatLS[3]; ?
? ?
? ? ? ? ? ? ? Buff_Send[10] ? := ? Buff_DatT1[1]; ?
? ? ? ? ? ? ? Buff_Send[11] ? := ? Buff_DatT1[2]; ?
? ?
? ? ? ? ? ? ? Buff_Send[12] ? := ? Buff_DatT2[1]; ?
? ? ? ? ? ? ? Buff_Send[13] ? := ? Buff_DatT2[2]; ?
? ?
? ? ? ? ? ? ? Buff_Send[14] ? := ? Buff_DatP[1]; ?
? ? ? ? ? ? ? Buff_Send[15] ? := ? Buff_DatP[2]; ?
? ?
? ? ? ? ? ? ? ? ? ? ? //CRC校驗:即校驗域前的幾個域的集合 ?
? ? ? ? ? ? ? ? ? ? ? I ? := ? CRC(Buff_Send[1],15); ?
? ? ? ? ? ? ? ? ? ? ? Buff_Send[16] ? := ? I ? div ? 256; ?
? ? ? ? ? ? ? ? ? ? ? Buff_Send[17] ? := ? I ? mod ? 256; ?
? ?
? ? ? ? ? ? ? //獲得string類型的測試傳輸幀 ?
? ? ? ? ? ? ? TempStr ? := ? ''; ?
? ? ? ? ? ? ? for ? I:= ? 1 ? to ? TempLen ? do ?
? ? ? ? ? ? ? ? ? TempStr ? := ? TempStr ? + ? inttohex(Buff_Send[i],2); ?
? ?
? ? ? ? ? ? ? BuffLen ? ? ? ? := ? TempLen ? * ? 2; ?
? ? ? ? ? ? ? PChar_Send ? := ? PChar(TempStr); ?
? ?
? ? ? ? ? ? ? //發送命令 ?
? ? ? ? ? ? ? //測試屏蔽 ?
? ? ? ? ? ? ? Rtl ? := ? ReadData(Usb_Index,PChar_Send,BuffLen); ?
? ?
? ? ? ? ? ? ? if ? Rtl ? then ?
? ? ? ? ? ? ? ? ? begin ?
? ? ? ? ? ? ? ? ? ? ? //讀取返回串 ?
? ? ? ? ? ? ? ? ? ? ? for ? I:= ? 0 ? to ? TempLen-1 ? do ?
? ? ? ? ? ? ? ? ? ? ? ? ? Buff_rev[I+1] ? := ? strtohex1(copy(PChar_Send,I*2+1,2),2); ?
? ?
? ? ? ? ? ? ? ? ? ? ? //CRC校驗 ?
? ? ? ? ? ? ? ? ? ? ? if ? CRC_Check=1 ? then ?
? ? ? ? ? ? ? ? ? ? ? ? ? begin ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TempStr ? := ? ''; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //校驗成功,讀出數據 ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //TempStr ? := ? TempStr ? + ? inttohex(Buff_rev[i+4],2); ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for ? I:= ? 0 ? to ? 2 ? do ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? begin ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatLC[I+1] ? := ? Buff_rev[I+4]; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatLS[I+1] ? := ? Buff_rev[I+7]; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? end; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for ? I:= ? 0 ? to ? 1 ? do ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? begin ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatT1[I+1] ? := ? Buff_rev[I+10]; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatT2[I+1] ? := ? Buff_rev[I+12]; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Buff_DatP[I+1] ? ? := ? Buff_rev[I+14]; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? end; ?
? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //數據處理 ?
? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Result ? ? := ? 1; ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //初始化接受串 ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for ? I:=1 ? to ? Maxlen ? do ? Buff_rev[I]:=0; ?
? ? ? ? ? ? ? ? ? ? ? ? ? end; ?
? ? ? ? ? ? ? ? ? end ?
? ? ? ? ? ? ? else ?
? ? ? ? ? ? ? ? ? begin ?
? ? ? ? ? ? ? ? ? ? ? ShowMessage('數據傳輸出錯,無法得到正確的值!','提示'); ?
? ? ? ? ? ? ? ? ? end; ?
? ? ? ? ? end ?
? ? ? else ?
? ? ? ? ? begin ?
? ? ? ? ? ? ? ShowMessage('沒有發現可用的Usb設備!','提示'); ?
? ? ? ? ? end; ?
? end;
對于傳輸幀,我現在有點疑惑: ?
? 我傳向下位機請求和從下位機得到數據都是以上面我和下位機開發人員定義的格式傳輸并不象下面Modbus中的例子,不知可行否? ?
? 因為我定義的幀中要獲取5個參數的值:LC由C0C1C2構成(高-低)、LS由S0S1S2構成、T1由T10T11構成、T2由T20T21構成、P由P0P1構成。 ?
? 下面是Modbus ? RTU中一個例子: ?
? 主機請求: ?
? 地址 ? ? 功能碼 ? ? 第一個寄存器的高位地址 ? ? 第一個寄存器的低位地址 ? ? 寄存器的數量的高位 ? ? 寄存器的數量的低位 ? 錯誤校驗 ? ?
? 01 ? 03 ? ? 00 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 38 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 00 ? 01 ? ? XX ? ?
? ?
? 從機應答: ? ?
? 地址 ? 功能碼 ? 字節數 ? 數據高字節 ? 數據低字節 ? 錯誤校驗 ? ?
? 01 ? 03 ? ? 2 ? ? ? 41 ? ? ? ? ? ? ? ? ? ? ? ? ? ? 24 ? ? ? ? ? ? ? ? ? ? ? ? ? XX ? ?
? ?
? 數據:16進制=4124,轉換成十進制=16676
//發送命令 ?
? ? ? ? ? ? ? //測試屏蔽 ?
? ? ? ? ? ? ? Rtl ? := ? ReadData(Usb_Index,PChar_Send,BuffLen); ?
? ?
? ReadData應該是讀吧? ?
? ?
? 你的例子: ?
? 請求: ?
? 0103 ? 00380001XX ?
? 01=>hdr ?
? 03=>cmd ?
? 00=>len ?
? 38=>crc ?
? 即無數據,后面的數據就錯了 ?
? ?
? 按協議,好像是這樣寫的 ?
? PRTUData ? = ? ^TRTUData; ?
? TRTUData ? = ? packed ? record ?
? ? ? hdr: ? Byte; ?
? ? ? cmd: ? Byte; ?
? ? ? len: ? Byte; ?
? ? ? data: ? array ? [0..0] ? of ? Byte; ?
? ? ? crc: ? Byte; ?
? end; ?
? ?
? data取決于len的長度
var ?
? ? ? P: ? PByte; ?
? ? ? rtuLen: ? Byte; ?
? ? ? rtu: ? PRTUData; ?
? begin ?
? ? ? rtuLen ? := ? SizeOf(TRTUData) ? + ? DataLen ? - ? 1; ?
? ? ? rtu ? := ? allocMem(rtuLen); ?
? ? ? rtu.hdr ? := ? $01; ?
? ? ? rtu.cmd ? := ? $02; ?
? ? ? rtu.len ? := ? DataLen; ?
? ? ? P ? := ? @rtu.data[0]; ?
? ? ? for ? I ? := ? 0 ? to ? DataLen ? - ? 1 ? do ?
? ? ? beg ?
? ? ? ? ? P^ ? := ? $XX; ?
? ? ? ? ? inc(P); ?
? ? ? end; ?
? ? ? P^ ? := ? crc(xxx); ? ? ? // ? P ? ==> ? crc ?
? ? ? WriteData(..., ? rtu, ? rtuLen) ?
? end;
先謝謝ERR0RC0DE() ? ?
? 我知道了,你是先發送命令,WriteData(..., ? rtu, ? rtuLen),然后在通過ReadData(Usb_Index,PChar_Send,BuffLen);讀取數據,是吧? ?
? ?
?
看不懂,^_^ ?
? ?
? ?
? 頂下!
有興趣的朋友歡迎繼續討論阿
總結
以上是生活随笔為你收集整理的遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: favorites 不是一个有效的短文件
- 下一篇: Visual Studio 2008 每