Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

177 rindas
6.0 KiB

  1. using ModbusDemo.Uitls;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO.Ports;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. namespace ModbusDemo.Device
  10. {
  11. public class ModbusRTU : IModbusRTU
  12. {
  13. private SerialPort _serialPort;
  14. public ModbusRTU(SerialPort serialPort)
  15. {
  16. _serialPort = serialPort;
  17. }
  18. /// <summary>
  19. /// 用来发送读写线圈的指令
  20. /// </summary>
  21. /// <param name="slaveAddress"></param>
  22. /// <param name="startAddress"></param>
  23. /// <param name="numberOfPoints"></param>
  24. /// <returns></returns>
  25. public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints)
  26. {
  27. if (!_serialPort.IsOpen)
  28. {
  29. MessageBox.Show("串口没有链接,请先链接");
  30. return null;
  31. }
  32. List<byte> sendByteList = new List<byte>();
  33. //设置从站地址
  34. sendByteList.Add(slaveAddress);
  35. //设置功能码
  36. sendByteList.Add(0x01);
  37. //设置起始地址的高位和低位
  38. sendByteList.Add(BitConverter.GetBytes(startAddress)[1]);
  39. sendByteList.Add(BitConverter.GetBytes(startAddress)[0]);
  40. //设置读取几个线圈的高位和低位
  41. sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[1]);
  42. sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[0]);
  43. //获取CRC校验码
  44. byte[] getCRC = sendByteList.ToArray();
  45. byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length);
  46. sendByteList.Add(resultCRC[0]);
  47. sendByteList.Add(resultCRC[1]);
  48. byte[] sendByte = sendByteList.ToArray();
  49. if (_serialPort.IsOpen)
  50. {
  51. // 清空接收缓冲区(避免残留数据干扰)
  52. _serialPort.DiscardInBuffer();
  53. _serialPort.Write(sendByte, 0, sendByte.Length);
  54. Thread.Sleep(300);
  55. byte[] response = new byte[_serialPort.BytesToRead];
  56. _serialPort.Read(response, 0, _serialPort.BytesToRead);
  57. return Parseresponse(response,numberOfPoints);
  58. }
  59. return null;
  60. }
  61. public bool[] Parseresponse(byte[] response, ushort numberOfPoints)
  62. {
  63. //判断发送回来的数据是否正确
  64. CheckData.CheckResponse(response);
  65. if (!CRCUitl.ValidateCRC(response))
  66. {
  67. MessageBox.Show("0x14:CRC校验错误");
  68. return null;
  69. }
  70. List<byte> responseList = new List<byte>(response);
  71. //移除前两位
  72. responseList.RemoveRange(0, 3);
  73. //移除后两位校验码
  74. responseList.RemoveRange(responseList.Count - 2, 2);
  75. responseList.Reverse();
  76. //数组反转之后,转为二进制字符
  77. List<string> StringList = responseList.Select(m => Convert.ToString(m, 2)).ToList();
  78. var result = "";
  79. foreach (var item in StringList)
  80. {
  81. result += item.PadLeft(8, '0');
  82. }
  83. //先将字符串转为数组,再反转,再转为字节数组
  84. char[] chars = result.ToArray().Reverse<char>().ToArray();
  85. bool[] ultimately = new bool[numberOfPoints];
  86. for (int i = 0; i < numberOfPoints; i++)
  87. {
  88. if (chars[i] == '1')
  89. {
  90. ultimately[i] = true;
  91. }
  92. else
  93. {
  94. ultimately[i] = false;
  95. }
  96. }
  97. return ultimately;
  98. }
  99. public void WriteCoil(byte slaveAddress, ushort startAddress, bool[] data)
  100. {
  101. List<byte> sendByteList = new List<byte>();
  102. //设置从站地址
  103. sendByteList.Add(slaveAddress);
  104. //设置功能码
  105. sendByteList.Add(0x0F);
  106. //设置起始地址的高位和低位
  107. sendByteList.Add(BitConverter.GetBytes(startAddress)[1]);
  108. sendByteList.Add(BitConverter.GetBytes(startAddress)[0]);
  109. //设置写入几个线圈
  110. sendByteList.Add(BitConverter.GetBytes(data.Length)[1]);
  111. sendByteList.Add(BitConverter.GetBytes(data.Length)[0]);
  112. // 计算字节数
  113. int byteCount = (data.Length + 7) / 8;
  114. sendByteList.Add((byte)byteCount);
  115. // 初始化字节数组
  116. byte[] coilBytes = new byte[byteCount];
  117. // 把bool数组转换为字节
  118. for (int i = 0; i < data.Length; i++)
  119. {
  120. int byteIndex = i / 8;
  121. int bitIndex = i % 8;
  122. if (data[i])
  123. {
  124. coilBytes[byteIndex] |= (byte)(1 << bitIndex);
  125. }
  126. }
  127. sendByteList.AddRange(coilBytes);
  128. //获取CRC校验码
  129. byte[] getCRC = sendByteList.ToArray();
  130. byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length);
  131. sendByteList.Add(resultCRC[0]);
  132. sendByteList.Add(resultCRC[1]);
  133. byte[] sendByte = sendByteList.ToArray();
  134. if (_serialPort.IsOpen)
  135. {
  136. // 清空接收缓冲区(避免残留数据干扰)
  137. _serialPort.DiscardInBuffer();
  138. _serialPort.Write(sendByte, 0, sendByte.Length);
  139. Thread.Sleep(300);
  140. byte[] response = new byte[_serialPort.BytesToRead];
  141. _serialPort.Read(response, 0, _serialPort.BytesToRead);
  142. //判断发送回来的数据是否正确
  143. CheckData.CheckResponse(response);
  144. if (!CRCUitl.ValidateCRC(response))
  145. {
  146. MessageBox.Show("0x14:CRC校验错误");
  147. }
  148. }
  149. }
  150. }
  151. }