/*-------------------------------------------------------------------------------------------------- * Func: 生成ModBus数据报文 * Time: 2010-6-28 * Ver.: V1.0 * Note: * 本方法对于主机: 生成查询报文 * 本方法对于从机: 若TxMsg->CmdCode为读命令,则生成返回数据报文 * 若TxMsg->CmdCode为写命令,则生成应答报文 * 若收到非法不可执行命令,则生成错误码状态报文 * * 本方法根据Msg->DataLenth指定生成是否含Datas域 * Infor: DevAddr[1]+CmdCode[1]+StartReg[2]+RegCount[2]+CRC16[2] * Input: *Msg/报文结构 *Buffer/报文帧数据缓冲区 * --------------------------------------------------------------------------------------------------*/ public static int CreateTxMessage(ref Modbus CurModbus, ref byte[] TxBuffer) { int L = 0; TxBuffer[0] = (byte)CurModbus.TxMsg.DevAddr; //写入设备地址字节 TxBuffer[1] = (byte)CurModbus.TxMsg.CmdCode; //写入命令码字节 if (CurModbus.LocalMode == HostMode) { TxBuffer[2] = (byte)(CurModbus.TxMsg.RegStart >> 8); TxBuffer[3] = (byte)(CurModbus.TxMsg.RegStart); //写入起始地址 TxBuffer[4] = (byte)(CurModbus.TxMsg.RegCount >> 8); TxBuffer[5] = (byte)(CurModbus.TxMsg.RegCount); //写入寄存器个数 if (CurModbus.TxMsg.CmdCode == 0x03) { L = 6; } else { TxBuffer[6] = (byte)(CurModbus.TxMsg.DataLenth); //写入数据长度 L = 7; } for (int i = 0; i < CurModbus.TxMsg.DataLenth; i++) { TxBuffer[L + i] = CurModbus.TxMsg.DataBuffer[i]; //写入数据域 } L += CurModbus.TxMsg.DataLenth; } uint T = CheckTools.GetCrc16(TxBuffer, L); //求本帧数据校验码 TxBuffer[L] = (byte)(T); TxBuffer[L + 1] = (byte)(T >> 8); //写入CRC16到帧尾部 return(L + 2); //设定发送帧长度 }
private void button9_Click(object sender, EventArgs e) { int T; bool R; COMM_UpdateMsg("设置参数到设备 [0x" + CurConfig.Config.Address.ToString("X2") + "]", 0, " ", 1); T = CheckTools.RTC_EncodeTime(DateTime.Now.AddSeconds(1)); DateTime DT = RTC_DecodeTime(T); CurConfig.Config.ProductDate = DT; byte[] ConfigDatas = new byte[200]; ModbusPacket_AddData32(ref ConfigDatas, 0, RTC_EncodeTime(CurConfig.Config.ProductDate)); R = CommByRS232.WritePacket(CurConfig.Config.Address, 2004, 2, ConfigDatas, 4); if (R == false) { COMM_UpdateMsg("失败", 0, "同步错误!", 0); } else { COMM_UpdateMsg("", 100, "读取成功!", 1); MessageBox.Show(" 同步成功!当前设备内部时间:" + DT.ToString(), "消息", MessageBoxButtons.OK, MessageBoxIcon.None); } }
/*-------------------------------------------------------------------------------------------------- * Func: 截取请求报文中的数据段 * Time: 2010-6-28 * Ver.: V1.0 * Note: 本方法根据RegCount和Lenth自动判断是否有合适的Datas域 * Infor: DevAddr[1]+CmdCode[1]+StartReg[2]+RegCount[2]+Datas[RegCount*2]+CRC16[2] * Input: *Data/原如数据报文 Lenth/报文总长度 *Msg/返回的报文信息 * return: 0/报文信息提取成功 11/报文长度不足 12/报文数据校验错误 13/数据报分长度错误 0xFF/地址不匹配 * --------------------------------------------------------------------------------------------------*/ public static int ExpendRxMessage(ref Modbus CurModbus, byte[] RxBuffer, int RxLenth) { int T, P; if (CurModbus.LocalMode != HostMode) { if ((RxBuffer[0]) != CurModbus.LocalAddr) { return(0xFF); } } if (RxLenth < 5) { return(DataLenthError); //判断报文长度是否正常 } T = RxBuffer[RxLenth - 1]; T <<= 8; T |= (int)RxBuffer[RxLenth - 2]; P = (int)CheckTools.GetCrc16(RxBuffer, RxLenth - 2); //获取报文CRC16检验码 if (T != P) { return(CrcCheckError); //检验CRC16码是否正确 } CurModbus.RxMsg.DevAddr = RxBuffer[0]; //取设备地址 CurModbus.RxMsg.CmdCode = RxBuffer[1]; //取命令码 if (CurModbus.LocalMode == HostMode) { if (CurModbus.RxMsg.CmdCode == CmdCode_Read) { CurModbus.RxMsg.DataLenth = RxBuffer[2]; for (int i = 0; i < CurModbus.TxMsg.RegCount * 2; i++) { CurModbus.RxMsg.DataBuffer[i] = RxBuffer[i + 3]; } } else if ((CurModbus.RxMsg.CmdCode & 0x80) == 0x80) { CurModbus.RxMsg.DataLenth = 1; CurModbus.RxMsg.DataBuffer[0] = RxBuffer[2]; } else if (CurModbus.RxMsg.CmdCode == CmdCode_Write) { CurModbus.RxMsg.DataLenth = RxBuffer[2]; } } return(MsgSuccess); }