diff --git a/GeneralGommunication/ModbusAsciiServer.cs b/GeneralGommunication/ModbusAsciiServer.cs index 8244903cf51b0afba3dd50c38894179550d6205a..0ac251928a24dc69f513d780959b75ed37fa0afa 100644 --- a/GeneralGommunication/ModbusAsciiServer.cs +++ b/GeneralGommunication/ModbusAsciiServer.cs @@ -24,7 +24,8 @@ namespace GeneralGommunication MBA_STATUS_0A = 2 } ModbusAsciiStatus status; - ModbusRegReadWriteHandler regRead; + ModbusRegReadWriteHandler regRead_Holding; + ModbusRegReadWriteHandler regRead_Input; ModbusRegReadWriteHandler regWrite; Action<IEnumerable<byte>> sendMsg; @@ -34,10 +35,14 @@ namespace GeneralGommunication //上一次接收数æ®çš„时间 DateTime lastRecMsgTime; - public void Init(ModbusRegReadWriteHandler regRead, ModbusRegReadWriteHandler regWrite, + public void Init( + ModbusRegReadWriteHandler regRead_Holding, + ModbusRegReadWriteHandler regRead_Input, + ModbusRegReadWriteHandler regWrite, Action<IEnumerable<byte>> sendMsg, out Action<IEnumerable<byte>> recMsg) { - this.regRead = regRead; + this.regRead_Holding = regRead_Holding; + this.regRead_Input = regRead_Input; this.regWrite = regWrite; this.sendMsg = sendMsg; recMsg = RecMsg; @@ -54,7 +59,7 @@ namespace GeneralGommunication /// <summary> - /// Read REGs + /// Read Holding REGs /// </summary> /// <param name="buf">ä¼ å…¥é€šè®¯å—å…ƒ</param> /// <param name="startIndex"></param> @@ -118,7 +123,12 @@ namespace GeneralGommunication midBuf.Add((byte)(number * 2)); UInt16[] regValues = new UInt16[number]; - bool ret = this.regRead(deviceNo, startAddr, regValues); + if (this.regRead_Holding == null) + { + //读å–失败,没有设备,ä¸ç”¨å›žå¤ + return; + } + bool ret = this.regRead_Holding(deviceNo, startAddr, regValues); if (!ret) { //读å–失败,没有设备,ä¸ç”¨å›žå¤ @@ -133,7 +143,90 @@ namespace GeneralGommunication Modbus_AddLrcAndSend(midBuf); } + /// <summary> + /// Read Input REGs + /// </summary> + /// <param name="buf">ä¼ å…¥é€šè®¯å—å…ƒ</param> + /// <param name="startIndex"></param> + /// <param name="len">buf长度</param> + void Modbus_Func04(IEnumerable<byte> buf, int startIndex, int len) + { + + //请求 + //0. ':' 0x3A + //1. slave address : 2bytes ascii + //2. Function : 2bytes ascii + //3. Starting Address Hi : 2bytes ascii + //4. Starting Address Lo : 2bytes ascii + //5. Number of Register Hi : 2bytes ascii + //6. Number of Register Lo : 2bytes ascii + //7. LRC : 2bytes ascii + //8. 0x0D 0x0A + + //å“应 + //0. ':' 0x3A + //1. slave address : 2bytes ascii + //2. Function : 2bytes ascii + //3. Number * 2 : 2bytes ascii + + //下é¢é‡å¤ Number 次 + //4. Data Hi : 2bytes ascii + //5. Data Lo : 2bytes ascii + + //6. LRC : 2bytes ascii + //7. 0x0D 0x0A + + + //example: 下é¢ä¸º ASCII + //请求 + //: 01 03 00 01 00 01 ?? (0X0D) (0X0A) + //å“应 + //: 01 03 02 12 34 ?? (0X0D) (0X0A) + + //buf å·²ç»æ˜¯ ascii转hex åŽç»“果。 从 slave address 开始,没有LRC + if (len < 6) + { + Modbus_DefaultCallback(buf, startIndex, MB_ERR_LEN);//指令异常 + return; + } + + byte deviceNo = buf.ElementAt(startIndex); + UInt16 startAddr = buf.ToUInt16_Big_Endian(startIndex + 2); + UInt16 number = buf.ToUInt16_Big_Endian(startIndex + 4); + + if (number == 0) + { + Modbus_DefaultCallback(buf, startIndex, MB_ERR_NUM_0);//指令异常 + return; + } + if (number > 50)//é™åˆ¶æ•°é‡ï¼Œå› 为缓å˜åŒºä¸å¤Ÿå¤§ + number = 50; + List<byte> midBuf = new List<byte>(); + midBuf.Add(deviceNo); + midBuf.Add(0x04); + midBuf.Add((byte)(number * 2)); + + UInt16[] regValues = new UInt16[number]; + if (this.regRead_Input == null) + { + //读å–失败,没有设备,ä¸ç”¨å›žå¤ + return; + } + bool ret = this.regRead_Input(deviceNo, startAddr, regValues); + if (!ret) + { + //读å–失败,没有设备,ä¸ç”¨å›žå¤ + return; + } + + for (int i = 0; i < number; i++) + { + midBuf.AddRange(regValues[i].GetBytes_Big_endian()); + } + + Modbus_AddLrcAndSend(midBuf); + } /// <summary> /// Write Single REG /// </summary> @@ -183,6 +276,8 @@ namespace GeneralGommunication UInt16 regValue = buf.ToUInt16_Big_Endian(startIndex + 4); UInt16[] regValues = new UInt16[] { regValue }; + if (this.regWrite == null) + return;//写入失败,没有设备,ä¸ç”¨å›žå¤ bool ret = this.regWrite(deviceNo, startAddr, regValues); if (!ret) { @@ -282,6 +377,8 @@ namespace GeneralGommunication index += 2; regValues[i] = regValue; } + if (this.regWrite == null) + return;//写入失败,没有设备,ä¸ç”¨å›žå¤ bool ret = this.regWrite(deviceNo, startAddr, regValues); if (!ret) @@ -470,6 +567,9 @@ namespace GeneralGommunication case 0x03: Modbus_Func03(midBuf, 0, adu_len); break; + case 0x04: + Modbus_Func04(midBuf, 0, adu_len); + break; //case 0x05: // Modbus_Func05(buf, adu_len); // break; diff --git a/GeneralGommunication/ModbusRtuServer.cs b/GeneralGommunication/ModbusRtuServer.cs index f6b6436aa21667edf2f519961d62f376eda6b8c0..d127e5dc85818499576461608aa0e7bbb518723e 100644 --- a/GeneralGommunication/ModbusRtuServer.cs +++ b/GeneralGommunication/ModbusRtuServer.cs @@ -19,7 +19,7 @@ namespace GeneralGommunication const byte MB_ERR_CNT = 0x03;//å—节数!=寄å˜å™¨æ•°é‡*2 const byte MB_ERR_NOFUNC = 0x05;//没有这个func - + ModbusRegReadWriteHandler regRead_Input; ModbusRegReadWriteHandler regRead; ModbusRegReadWriteHandler regWrite; Action<IEnumerable<byte>> sendMsg; @@ -30,10 +30,11 @@ namespace GeneralGommunication System.Threading.Timer timer3d5t;//通讯包的 3.5T 时间间隔。 实际åªæ˜¯ 15ms定时而已 - public void Init(ModbusRegReadWriteHandler regRead, ModbusRegReadWriteHandler regWrite, + public void Init(ModbusRegReadWriteHandler regRead, ModbusRegReadWriteHandler regRead_Input, ModbusRegReadWriteHandler regWrite, Action<IEnumerable<byte>> sendMsg, out Action<IEnumerable<byte>> recMsg) { this.regRead = regRead; + this.regRead_Input = regRead_Input; this.regWrite = regWrite; this.sendMsg = sendMsg; recMsg = RecMsg; @@ -135,6 +136,13 @@ namespace GeneralGommunication midBuf.Add((byte)(number * 2)); UInt16[] regValues = new UInt16[number]; + if (this.regRead == null) + { + //读å–失败,没有设备,ä¸ç”¨å›žå¤ + logger.Debug($"REQ 读å–失败,没有设置regRead,ä¸ç”¨å›žå¤"); + sendBuf = null; + return req_len; + } bool ret = this.regRead(deviceNo, startAddr, regValues); if (!ret) { @@ -154,7 +162,109 @@ namespace GeneralGommunication //Modbus_AddCrcAndSend(midBuf); } + /// <summary> + /// 读寄å˜å™¨, 返回已ç»å¤„ç†çš„长度 + /// </summary> + /// <param name="buf">接收缓冲</param> + /// <param name="startIndex">æ•°æ®å¼€å§‹åºå·</param> + /// <param name="len">æ•°æ®é•¿åº¦</param> + /// <returns></returns> + int Modbus_Func04(IEnumerable<byte> buf, int startIndex, int len, out byte[] sendBuf) + { + //请求 + //1. slave address : 1byte + //2. Function : 1byte + //3. Starting Address Hi : 1byte + //4. Starting Address Lo : 1byte + //5. Number of Register Hi : 1byte + //6. Number of Register Lo : 1byte + //7. CRC16 : 2bytes + + //å“应 + //1. slave address : 1byte + //2. Function : 1byte + //3. Number * 2 : 1byte + + //下é¢é‡å¤ Number 次 + //4. Data Hi : 1byte + //5. Data Lo : 1byte + + //6. CRC16 : 2bytes + + //example: + //请求 + //01 03 00 01 00 01 ?? ?? + //å“应 + //01 03 02 12 34 ?? ?? + + int req_len = 8; + //buf 从 slave address 开始 + if (len < req_len) + { + logger.Error($"REQ 指令å—节数ä¸è¶³"); + sendBuf = Modbus_DefaultCallback(buf, startIndex, MB_ERR_LEN);//指令异常 + return len; + } + + + //CRC + int adu_len = req_len - 2;//去除crcåŽçš„æ•°æ®åŒ…é•¿ + + UInt16 crc = buf.CRC16(startIndex, req_len - 2); + UInt16 rec_crc = buf.ToUInt16_Little_Endian(startIndex + req_len - 2);//CRC 是 å°ç«¯æ¨¡å¼ + + if (crc != rec_crc) + { + logger.Error($"REQ CRC æ ¡éªŒå‡ºé”™ 接收:{rec_crc:X4} 计算:{crc:X4}"); + + sendBuf = Modbus_DefaultCallback(buf, startIndex, MB_ERR_LRC);//指令异常 + return len;//æŒ‡ä»¤å¼‚å¸¸ï¼Œåº”è¯¥å…¨éƒ¨åˆ é™¤ + } + + + byte deviceNo = recBuf[0]; + UInt16 startAddr = buf.ToUInt16_Big_Endian(startIndex + 2); + UInt16 number = buf.ToUInt16_Big_Endian(startIndex + 4); + if (number == 0) + { + logger.Error($"REQ 没有任何寄å˜å™¨"); + sendBuf = Modbus_DefaultCallback(buf, startIndex, MB_ERR_NUM_0);//指令异常 + return req_len; + } + if (number > 50)//é™åˆ¶æ•°é‡ï¼Œå› 为缓å˜åŒºä¸å¤Ÿå¤§ + number = 50; + List<byte> midBuf = new List<byte>(); + midBuf.Add(deviceNo); + midBuf.Add(0x04); + midBuf.Add((byte)(number * 2)); + + UInt16[] regValues = new UInt16[number]; + if (this.regRead_Input == null) + { + //读å–失败,没有设备,ä¸ç”¨å›žå¤ + logger.Debug($"REQ 读å–失败,没有设置regRead,ä¸ç”¨å›žå¤"); + sendBuf = null; + return req_len; + } + bool ret = this.regRead_Input(deviceNo, startAddr, regValues); + if (!ret) + { + //读å–失败,没有设备,ä¸ç”¨å›žå¤ + logger.Debug($"REQ 读å–失败,没有设备,ä¸ç”¨å›žå¤"); + sendBuf = null; + return req_len; + } + + for (int i = 0; i < number; i++) + { + midBuf.AddRange(regValues[i].GetBytes_Big_endian()); + } + + sendBuf = midBuf.ToArray(); + return req_len; + //Modbus_AddCrcAndSend(midBuf); + } /// <summary> /// Write Single REG /// </summary> diff --git a/GeneralGommunication/ModbusServer.cs b/GeneralGommunication/ModbusServer.cs index d1a85a7d5659b6cbf6d8d72d73cfc376318e49d8..e8508f2ae66653beb2f0536b6d54a711acdf0613 100644 --- a/GeneralGommunication/ModbusServer.cs +++ b/GeneralGommunication/ModbusServer.cs @@ -8,7 +8,9 @@ namespace GeneralGommunication { public interface IModbusServer { - void Init(ModbusRegReadWriteHandler regRead, ModbusRegReadWriteHandler regWrite, + void Init(ModbusRegReadWriteHandler regRead_Holding, + ModbusRegReadWriteHandler regRead_Input, + ModbusRegReadWriteHandler regWrite, Action<IEnumerable<byte>> sendMsg, out Action<IEnumerable<byte>> recMsg); }