/// <summary> /// 接收数据 /// </summary> /// <param name="socket"></param> /// <param name="timeout"></param> /// <param name="content"></param> /// <param name="conLen"></param> /// <param name="type"></param> /// <param name="tel"></param> /// <returns></returns> public static bool rdata(ref string protocol, Socket socket, int timeout, ref byte[] content, ref int conLen, ref byte type, ref string tel) { if (protocol == DTU._ZG_DTU) { return(ZG_DTU.rdata(socket, timeout, ref content, ref conLen, ref type, ref tel)); //1秒超时 等待注册数据 } else if (protocol == DTU._HD_DTU) { return(HD_DTU.rdata(socket, timeout, ref content, ref conLen, ref type, ref tel)); //1秒超时 等待注册数据 } else if (protocol == DTU._JBT_DTU) { return(JBT_DTU.rdata(socket, timeout, ref content, ref conLen, ref type, ref tel)); //1秒超时 等待注册数据 } else { //在DTU未注册之前, socket接收都是调用以下的代码 , try { byte[] buffer = new byte[GlobalPara.SEND_DATA_LENGTH]; //接收数据的数组 socket.ReceiveTimeout = timeout; int len = socket.Receive(buffer, buffer.Length, SocketFlags.None); protocol = DTU.CheckProtocolByRegisterData(buffer, len); if (protocol == DTU._ZG_DTU) { return(ZG_DTU.UnPack(buffer, len, ref content, ref conLen, ref type, ref tel)); } else if (protocol == DTU._HD_DTU) { return(HD_DTU.UnPack(buffer, len, ref content, ref conLen, ref type, ref tel)); } else if (protocol == DTU._JBT_DTU) { return(JBT_DTU.UnPack(buffer, len, ref content, ref conLen, ref type, ref tel)); } else { return(false); } } catch (SocketException) { return(false); } catch (Exception ex) { LogMg.AddError(ex); return(false); } } }
protected static void GetResponse(string protocol, Socket socket, int receiveTimeout, ref byte[] response) { //There is a bug in .Net 2.0 DataReceived Event that prevents people from using this //event as an interrupt to handle data (it doesn't fire all of the time). Therefore //we have to use the ReadByte command for a fixed length as it's been shown to be reliable. // for (int i = 0; i < response.Length; i++) //{ int len = 0; byte type = 0; string strtel = new string('0', 11); DTU.rdata(ref protocol, socket, receiveTimeout, ref response, ref len, ref type, ref strtel); // response[i] = (byte)();//sp.ReadByte()); // } }
/// <summary> /// 读寄存器或线圈 /// </summary> /// <param name="protocol">协议( ZG_DTU、HD_DTU或者JBT_DTU)</param> /// <param name="socket">socket</param> /// <param name="tel">DTU的Id,长得跟TEL相似,都是11位的</param> /// <param name="address">485总线上的设备地址</param> /// <param name="RegisterStartAdd">寄存器起始地址 寄存器个数为1,方法内部已写死。</param> /// <param name="ModbusfunctionCode">功能码 </param> /// <param name="dataType">寄存器类型 1代表16位无符号二进制的寄存器,2代表32位的寄存器</param> /// <param name="DecodeOrder">获取的数据的高低位顺序</param> /// <param name="receiveTimeout">超时时间 </param> /// <param name="channel">GPRS控制器的通道号,也是串口号</param> /// <param name="values">返回的value值 虽然是个数组,但数据只有一个,下标为0</param> /// <returns></returns> public static void SendFc(string protocol, Socket socket, string tel, byte address, ushort RegisterStartAdd, int ModbusfunctionCode, string dataType, string DecodeOrder, int receiveTimeout, byte channel, ModbusReturn modbusReturn) { int dataLength = 2; //16位无符号二进制的寄存器数据长度为两个字节 默认为16位寄存器 if (dataType == "2") //说明是"32位无符号二进制" 所以要用4个字节 { dataLength = 4; } //LogManager.AddDebug("dataLength=" + dataLength); byte[] message = new byte[8]; //Function 3 response buffer: byte[] response = new byte[5 + dataLength * 1]; //Build outgoing modbus message: // LogManager.AddDebug(" BuildMessage(" + address + ", " + ModbusfunctionCode + ", " + RegisterStartAdd + ", 1, ref message);"); BuildMessage(address, (byte)ModbusfunctionCode, RegisterStartAdd, ushort.Parse(dataType), ref message); //Send modbus message to Serial Port: string msg = ""; try { modbusReturn.sendMsg = message; DTU.SendUserData(protocol, socket, message, message.Length, tel, channel); //sp.Write(message, 0, message.Length); GetResponse(protocol, socket, receiveTimeout, ref response); modbusReturn.RecMsg = response; } catch (SocketException ex) { modbusReturn.ErrorMsg = ex.Message; modbusReturn.success = false; return; } catch (Exception ex) { LogMg.AddError(ex); modbusReturn.ErrorMsg = "Error in read event: " + ex.Message; modbusReturn.success = false; return; } //处理返回结果 if (CheckResponse(response)) { int datalength = response[2]; //数据长度(单位:字节) //LogManager.AddDebug("返回的数据长度datalength=" + datalength); //设置默认解码顺序 if (string.IsNullOrEmpty(DecodeOrder)) { if (datalength == 2) { DecodeOrder = "12"; } else if (datalength == 4) {//三四个字节为高位,一二两个字节为低位 DecodeOrder = "3412"; } } //解析返回的modbus数据 modbusReturn.value = 0; try { for (int i = 0; i < DecodeOrder.Length; i++) { int n = Convert.ToInt32(DecodeOrder[i].ToString()); modbusReturn.value <<= 8; modbusReturn.value += response[2 + n]; } } catch (Exception) { modbusReturn.ErrorMsg = "解析返回的modbus时出错,modbus指令为:" + msg; modbusReturn.success = false; return; } modbusReturn.ErrorMsg = "Read successful"; modbusReturn.success = true; return; } else { modbusReturn.ErrorMsg = "CRC error"; modbusReturn.success = false; return; } }
/// <summary> /// 写寄存器 /// </summary> /// <param name="socket"></param> /// <param name="address"></param> /// <param name="start"></param> /// <param name="registers"></param> /// <param name="values"></param> /// <returns></returns> public static void SendFc16(string protocol, Socket socket, string tel, byte address, ushort start, ushort registers, string dataType, int receiveTimeout, byte channel, short[] values, ModbusReturn modbusReturn) { // LogManager.AddDebug("SendFc16(Socket socket, byte " + address + ", ushort " + start + ", ushort " + registers + ", string " + dataType + ", int " + receiveTimeout + ", short " + values[0] + ")"); int dataLength = 2; //默认数据长度为两个字节 if (dataType == "2") //说明是"32位无符号二进制" 所以要用4个字节 { dataLength = 4; } //Message is 1 addr + 1 fcn + 2 start + 2 reg + 1 count + 2 * reg vals + 2 CRC byte[] message = new byte[9 + dataLength * registers]; //Function 16 response is fixed at 8 bytes byte[] response = new byte[8]; try { //Add bytecount to message: message[6] = (byte)(registers * dataLength); //Put write values into message prior to sending: for (int i = 0; i < registers; i++) { for (int j = 0; j < dataLength; j++) { message[7 + (dataLength * i) + j] = (byte)(values[i] >> 8 * (dataLength - j - 1)); //将value[i]转换成指定字节长度的字节数组, (高位在前,低位在后) message下标从第七个开始 } //message[7 + 2 * i] = (byte)(values[i] >> 8); //message[8 + 2 * i] = (byte)(values[i]); } //Build outgoing message: BuildMessage(address, (byte)16, start, registers, ref message); //string msg = ""; //for (int i = 0; i < message.Length; i++) //{ // msg += "\r\n message[" + i + "]= 值:" + message[i]; //} //LogManager.AddDebug("写 message.length=" + message.Length + msg); } catch (Exception ex) { LogMg.AddError(ex); } //Send Modbus message to Serial Port: try { modbusReturn.sendMsg = message; DTU.SendUserData(protocol, socket, message, message.Length, tel, channel); //sp.Write(message, 0, message.Length); GetResponse(protocol, socket, receiveTimeout, ref response); modbusReturn.RecMsg = response; } catch (Exception err) { modbusReturn.ErrorMsg = "Error in write event: " + err.Message; modbusReturn.success = false; return; } //Evaluate message: if (CheckResponse(response)) { modbusReturn.ErrorMsg = "Write successful"; modbusReturn.success = true; return; } else { modbusReturn.ErrorMsg = "CRC error"; modbusReturn.success = false; return; } /* } * else * { * modbusStatus = "Serial port not open"; * return false; * } * */ }