|
- using ModbusDemo.Uitls;
- using System;
- using System.Collections.Generic;
- using System.IO.Ports;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
-
- namespace ModbusDemo.Device
- {
- public class ModbusRTU : IModbusRTU
- {
- private SerialPort _serialPort;
-
- public ModbusRTU(SerialPort serialPort)
- {
- _serialPort = serialPort;
- }
- /// <summary>
- /// 用来发送读写线圈的指令
- /// </summary>
- /// <param name="slaveAddress"></param>
- /// <param name="startAddress"></param>
- /// <param name="numberOfPoints"></param>
- /// <returns></returns>
- public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints)
- {
-
- List<byte> sendByteList = new List<byte>();
- //设置从站地址
- sendByteList.Add(slaveAddress);
- //设置功能码
- sendByteList.Add(0x01);
- //设置起始地址的高位和低位
- sendByteList.Add(BitConverter.GetBytes(startAddress)[1]);
- sendByteList.Add(BitConverter.GetBytes(startAddress)[0]);
- //设置读取几个线圈的高位和低位
- sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[1]);
- sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[0]);
- //获取CRC校验码
- byte[] getCRC = sendByteList.ToArray();
- byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length);
- sendByteList.Add(resultCRC[0]);
- sendByteList.Add(resultCRC[1]);
-
- byte[] sendByte = sendByteList.ToArray();
- if (_serialPort.IsOpen)
- {
- // 清空接收缓冲区(避免残留数据干扰)
- _serialPort.DiscardInBuffer();
-
- _serialPort.Write(sendByte, 0, sendByte.Length);
- Thread.Sleep(300);
- byte[] response = new byte[_serialPort.BytesToRead];
- _serialPort.Read(response, 0, _serialPort.BytesToRead);
- return Parseresponse(response,numberOfPoints);
- }
-
-
- return null;
- }
-
-
- public bool[] Parseresponse(byte[] response, ushort numberOfPoints)
- {
- //判断发送回来的数据是否正确
- CheckData.CheckResponse(response);
-
- if (!CRCUitl.ValidateCRC(response))
- {
- MessageBox.Show("0x14:CRC校验错误");
- return null;
- }
- List<byte> responseList = new List<byte>(response);
- //移除前两位
- responseList.RemoveRange(0, 3);
- //移除后两位校验码
- responseList.RemoveRange(responseList.Count - 2, 2);
- responseList.Reverse();
- //数组反转之后,转为二进制字符
- List<string> StringList = responseList.Select(m => Convert.ToString(m, 2)).ToList();
-
- var result = "";
-
- foreach (var item in StringList)
- {
- result += item.PadLeft(8, '0');
- }
- //先将字符串转为数组,再反转,再转为字节数组
- char[] chars = result.ToArray().Reverse<char>().ToArray();
- bool[] f = new bool[numberOfPoints];
- for (int i = 0; i < numberOfPoints; i++)
- {
- if (chars[i] == '1')
- {
- f[i] = true;
- }
- else
- {
- f[i] = false;
- }
- }
- return f;
- }
-
- }
- }
|