Modbus16Utils.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace Wit.SDK.Modular.Sensor.Utils
  7. {
  8. /// <summary>
  9. /// Modbus16工具类
  10. /// </summary>
  11. public class Modbus16Utils
  12. {
  13. /// <summary>
  14. /// 获得CRC16_Modbus效验,低位在前,高位在后
  15. /// </summary>
  16. /// <param name="byteData">要进行计算的字节数组</param>
  17. /// <returns>计算后的数组</returns>
  18. public static byte[] GetCrc16(byte[] bytes)
  19. {
  20. byte crcRegister_H = 0xFF, crcRegister_L = 0xFF;// 预置一个值为 0xFFFF 的 16 位寄存器
  21. byte polynomialCode_H = 0xA0, polynomialCode_L = 0x01;// 多项式码 0xA001
  22. for (int i = 0; i < bytes.Length; i++)
  23. {
  24. crcRegister_L = (byte)(crcRegister_L ^ bytes[i]);
  25. for (int j = 0; j < 8; j++)
  26. {
  27. byte tempCRC_H = crcRegister_H;
  28. byte tempCRC_L = crcRegister_L;
  29. crcRegister_H = (byte)(crcRegister_H >> 1);
  30. crcRegister_L = (byte)(crcRegister_L >> 1);
  31. // 高位右移前最后 1 位应该是低位右移后的第 1 位:如果高位最后一位为 1 则低位右移后前面补 1
  32. if ((tempCRC_H & 0x01) == 0x01)
  33. {
  34. crcRegister_L = (byte)(crcRegister_L | 0x80);
  35. }
  36. if ((tempCRC_L & 0x01) == 0x01)
  37. {
  38. crcRegister_H = (byte)(crcRegister_H ^ polynomialCode_H);
  39. crcRegister_L = (byte)(crcRegister_L ^ polynomialCode_L);
  40. }
  41. }
  42. }
  43. return new byte[] { crcRegister_L, crcRegister_H };
  44. }
  45. /// <summary>
  46. /// 获得CRC16_Modbus效验,低位在前,高位在后
  47. /// </summary>
  48. /// <param name="byteData">要进行计算的字节数组</param>
  49. /// <param name="length">长度</param>
  50. /// <returns>计算后的数组</returns>
  51. public static byte[] GetCrc16(byte[] byteData, int length)
  52. {
  53. byte[] CRC = new byte[2];
  54. ushort wCrc = 0xFFFF;
  55. for (int i = 0; i < length; i++)
  56. {
  57. wCrc ^= Convert.ToUInt16(byteData[i]);
  58. for (int j = 0; j < 8; j++)
  59. {
  60. if ((wCrc & 0x0001) == 1)
  61. {
  62. wCrc >>= 1;
  63. wCrc ^= 0xA001;//异或多项式
  64. }
  65. else
  66. {
  67. wCrc >>= 1;
  68. }
  69. }
  70. }
  71. CRC[1] = (byte)((wCrc & 0xFF00) >> 8);//高位在后
  72. CRC[0] = (byte)(wCrc & 0x00FF); //低位在前
  73. return CRC;
  74. }
  75. /// <summary>
  76. /// 获得写入的modbus指令
  77. /// </summary>
  78. /// <param name="addr"></param>
  79. /// <param name="reg"></param>
  80. /// <param name="value"></param>
  81. /// <param name="resultBytes"></param>
  82. /// <returns>成功返回0</returns>
  83. public static int GetWrite(byte addr, int reg, int value, out byte[] resultBytes)
  84. {
  85. byte[] reghl = GetHL(reg);
  86. byte[] valuehl = GetHL(value);
  87. resultBytes = new byte[] { addr, 0x06, reghl[0], reghl[1], valuehl[0], valuehl[1] };
  88. resultBytes = resultBytes.Concat(GetCrc16(resultBytes)).ToArray();
  89. return 0;
  90. }
  91. /// <summary>
  92. /// 写入的modbus指令
  93. /// </summary>
  94. /// <param name="addr"></param>
  95. /// <param name="reg"></param>
  96. /// <param name="value"></param>
  97. /// <returns></returns>
  98. public static byte[] GetWrite(byte addr, int reg, int value)
  99. {
  100. byte[] resultBytes = null;
  101. GetWrite(addr, reg, value, out resultBytes);
  102. return resultBytes;
  103. }
  104. /// <summary>
  105. /// 读取的modbus指令
  106. /// </summary>
  107. /// <param name="addr"></param>
  108. /// <param name="reg"></param>
  109. /// <param name="count"></param>
  110. /// <param name="resultBytes"></param>
  111. /// <returns>成功返回0</returns>
  112. public static int GetRead(byte addr, int reg, int count, out byte[] resultBytes)
  113. {
  114. byte[] reghl = GetHL(reg);
  115. byte[] counthl = GetHL(count);
  116. resultBytes = new byte[] { addr, 0x03, reghl[0], reghl[1], counthl[0], counthl[1] };
  117. resultBytes = resultBytes.Concat(GetCrc16(resultBytes)).ToArray();
  118. return 0;
  119. }
  120. /// <summary>
  121. /// 读取的modbus指令
  122. /// </summary>
  123. /// <param name="addr"></param>
  124. /// <param name="reg"></param>
  125. /// <param name="count"></param>
  126. /// <returns></returns>
  127. public static byte[] GetRead(byte addr, int reg, int count)
  128. {
  129. byte[] resultBytes = null;
  130. GetRead(addr,reg,count, out resultBytes);
  131. return resultBytes;
  132. }
  133. /// <summary>
  134. /// 获得高低位,高位在前
  135. /// </summary>
  136. /// <param name="value"></param>
  137. /// <returns></returns>
  138. public static byte[] GetHL(int value)
  139. {
  140. return new byte[] { (byte)(value >> 8), (byte)(value << 8 >> 8) };
  141. }
  142. /// <summary>
  143. /// 获得高低位,低位在前
  144. /// </summary>
  145. /// <param name="value"></param>
  146. /// <returns></returns>
  147. public static byte[] GetLH(int value)
  148. {
  149. return new byte[] { (byte)(value << 8 >> 8), (byte)(value >> 8) };
  150. }
  151. /// <summary>
  152. /// 检查校验位
  153. /// </summary>
  154. /// <param name="data"></param>
  155. /// <returns></returns>
  156. public static bool CheckModbusCrc16(byte[] data)
  157. {
  158. if (data == null)
  159. {
  160. return false;
  161. }
  162. if (data.Length < 3)
  163. {
  164. return false;
  165. }
  166. byte[] v = GetCrc16(data, data.Length - 2);
  167. if (v.Length < 2)
  168. {
  169. return false;
  170. }
  171. if (v[0] != data[data.Length - 2])
  172. {
  173. return false;
  174. }
  175. if (v[1] != data[data.Length - 1])
  176. {
  177. return false;
  178. }
  179. return true;
  180. }
  181. /// <summary>
  182. /// 查询返回的字节里有没有发送的命令的回传
  183. /// </summary>
  184. /// <param name="sendByte"></param>
  185. /// <param name="returnByte"></param>
  186. /// <param name="modbus"></param>
  187. /// <returns>查找成功返回true,查找失败返回false</returns>
  188. public static bool FindModbus(byte[] sendByte, byte[] returnByte, out byte[] modbus)
  189. {
  190. int height = sendByte[4];
  191. int low = sendByte[5];
  192. // 得到长度
  193. int len = 5 + (height << 8 | low) * 2;
  194. // 如果没有返回结果,或者返回结果根本不够长
  195. if (returnByte == null || returnByte.Length < len)
  196. {
  197. modbus = new byte[0];
  198. return false;
  199. }
  200. // 遍历返回结果查找
  201. for (int i = 0; i <= returnByte.Length - len; i++)
  202. {
  203. byte rAddr = returnByte[i];
  204. byte mark = 0x03;
  205. byte[] cCrc = GetCrc16(returnByte.Skip(i).Take(len - 2).ToArray());
  206. byte rCrcH = returnByte[i + len - 2];
  207. byte rCrcL = returnByte[i + len - 1];
  208. // 如果全部通过
  209. if (sendByte[0] == rAddr && mark == sendByte[1] && rCrcH == cCrc[0] && rCrcL == cCrc[1])
  210. {
  211. modbus = returnByte.Skip(i).Take(len).ToArray();
  212. return true;
  213. }
  214. }
  215. modbus = new byte[0];
  216. return false;
  217. }
  218. }
  219. }