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;
}
///
/// 用来发送读写线圈的指令
///
///
///
///
///
public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints)
{
List sendByteList = new List();
//设置从站地址
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 responseList = new List(response);
//移除前两位
responseList.RemoveRange(0, 3);
//移除后两位校验码
responseList.RemoveRange(responseList.Count - 2, 2);
responseList.Reverse();
//数组反转之后,转为二进制字符
List 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().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;
}
}
}