25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.6 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. List<byte> sendByteList = new List<byte>();
  28. //设置从站地址
  29. sendByteList.Add(slaveAddress);
  30. //设置功能码
  31. sendByteList.Add(0x01);
  32. //设置起始地址的高位和低位
  33. sendByteList.Add(BitConverter.GetBytes(startAddress)[1]);
  34. sendByteList.Add(BitConverter.GetBytes(startAddress)[0]);
  35. //设置读取几个线圈的高位和低位
  36. sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[1]);
  37. sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[0]);
  38. //获取CRC校验码
  39. byte[] getCRC = sendByteList.ToArray();
  40. byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length);
  41. sendByteList.Add(resultCRC[0]);
  42. sendByteList.Add(resultCRC[1]);
  43. byte[] sendByte = sendByteList.ToArray();
  44. if (_serialPort.IsOpen)
  45. {
  46. // 清空接收缓冲区(避免残留数据干扰)
  47. _serialPort.DiscardInBuffer();
  48. _serialPort.Write(sendByte, 0, sendByte.Length);
  49. Thread.Sleep(300);
  50. byte[] response = new byte[_serialPort.BytesToRead];
  51. _serialPort.Read(response, 0, _serialPort.BytesToRead);
  52. return Parseresponse(response,numberOfPoints);
  53. }
  54. return null;
  55. }
  56. public bool[] Parseresponse(byte[] response, ushort numberOfPoints)
  57. {
  58. //判断发送回来的数据是否正确
  59. CheckData.CheckResponse(response);
  60. if (!CRCUitl.ValidateCRC(response))
  61. {
  62. MessageBox.Show("0x14:CRC校验错误");
  63. return null;
  64. }
  65. List<byte> responseList = new List<byte>(response);
  66. //移除前两位
  67. responseList.RemoveRange(0, 3);
  68. //移除后两位校验码
  69. responseList.RemoveRange(responseList.Count - 2, 2);
  70. responseList.Reverse();
  71. //数组反转之后,转为二进制字符
  72. List<string> StringList = responseList.Select(m => Convert.ToString(m, 2)).ToList();
  73. var result = "";
  74. foreach (var item in StringList)
  75. {
  76. result += item.PadLeft(8, '0');
  77. }
  78. //先将字符串转为数组,再反转,再转为字节数组
  79. char[] chars = result.ToArray().Reverse<char>().ToArray();
  80. bool[] f = new bool[numberOfPoints];
  81. for (int i = 0; i < numberOfPoints; i++)
  82. {
  83. if (chars[i] == '1')
  84. {
  85. f[i] = true;
  86. }
  87. else
  88. {
  89. f[i] = false;
  90. }
  91. }
  92. return f;
  93. }
  94. }
  95. }