using System; using System.IO.Ports; using System.Windows.Forms; using System.Threading; using HardwareConfig; using BaseLibRWFile; namespace BaseLibComm { public class ModbusRTU { public static ModbusRTU Ins = new ModbusRTU(); //private SerialPort MyCom;//定义串口类对象 //private int CurrentAddr;//定义当前通讯设备的地址 //private byte[] bReceiveData = new byte[1024];//最大接受的1024个字节 //private string mTempStr; //private byte ReceiveByte; private int mReceiveByteCount; //private bool bCommWell; private byte CRCHi = 0xFF; private byte CRCLo = 0xFF; //定义超时定时器 250mm private System.Timers.Timer tmrTimeOut = new System.Timers.Timer(500);//实例化Timer类,设置间隔时间为10000毫秒; //public string strErrMsg;//错误信息 //public string strReceivCommandData, strSendCommandData;//定义发送及接收数据字符串 //public bool RtuRunFlag = true; public long iWordStartAddr, iBitStartAddr;//保持寄存器及输出线圈的起始地址 public int WordLength, iBitLen;//保持寄存器及输出线圈长度 //public short[,] WordValueArray = new short[16, 256];//定义最大保持寄存器二维数组,1维表示设备站号,二维表示数据 //public bool[,] BitVaueArray = new bool[16, 256];//定义输出线圈二维数组,1维表示设备站号,二维表示数据 //public bool[] bComRunNomalFlag = new bool[16];//false 通讯正常 true 通讯异常 最大16个设备 //public bool comBusying; //串口忙 //public bool isOpend; //串口打开状态 public ModbusRTU() { //MyCom = new SerialPort(); //RtuRunFlag = true; //throw new System.NotImplementedException(); } // LRC CHECK FROM CSDN MODIFY #region private string LRC(string strLRC) { int d_lrc = 0; string h_lrc = ""; int l = strLRC.Length; for (int c = 0; c < l; c = c + 2) { string c_data = strLRC.Substring(c, 2); d_lrc = d_lrc + (Int32)Convert.ToByte(c_data, 16); //d_lrc = d_lrc + Convert.ToInt32(c_data); } if (d_lrc >= 255) d_lrc = d_lrc % 0x100; h_lrc = Convert.ToInt32(~d_lrc + 1).ToString("X"); if (h_lrc.Length > 2) h_lrc = h_lrc.Substring(h_lrc.Length - 2, 2); return h_lrc; } #endregion //CRC校验 FROM Google #region private static readonly byte[] aucCRCHi = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 }; private static readonly byte[] aucCRCLo = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 }; private void Crc16(byte[] pucFrame, int usLen) { int i = 0; CRCHi = 0xFF; CRCLo = 0xFF; UInt16 iIndex = 0x0000; while (usLen-- > 0) { iIndex = (UInt16)(CRCLo ^ pucFrame[i++]); CRCLo = (byte)(CRCHi ^ aucCRCHi[iIndex]); CRCHi = aucCRCLo[iIndex]; } } #endregion //设置串口并打开串口 public bool OpenMyCom(StSerialPort st) { try { for (int i = 0; i <= 15; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].bComRunNomalFlag[i] = false; } //先关闭已经打开的串口 if (st.serialPort.IsOpen) { st.serialPort.Close(); } st.serialPort.ReceivedBytesThreshold = 1; st.serialPort.DataReceived += new SerialDataReceivedEventHandler(MyCom_DataReceived);//DataReceived事件委托 //打开串口 st.serialPort.Open(); //设置超时定时器属性 tmrTimeOut.Elapsed += new System.Timers.ElapsedEventHandler(commTimeOut);//到达时间的时候执行事件; tmrTimeOut.AutoReset = true;//设置是执行一次(false)还是一直执行(true); tmrTimeOut.Enabled = false;//是否执行System.Timers.Timer.Elapsed事件; st.comBusying = false; SerialPortManager.DicSerialPort[st.serialPort.PortName] = st; //bCommWell = false; return true; } catch (Exception ex) { string str = "Modbus串口打开失败:"; Msg.Show($"{str}\r\n{ex}", $"{str}\r\nModbus serial port opening failed:\r\n{ex}", $"{str}\r\nKhông mở được cổng nối tiếp Modbus:\r\n{ex}", "Error", msgicon: MessageBoxIcon.Error); return false; } finally { } } public void CloseMyCom(StSerialPort st) { st.serialPort.Close(); } //DataReceived事件委托方法 每个协议都需重写DataReceived private void MyCom_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { SerialPort sp = sender as SerialPort; int i; string mTempStr; mReceiveByteCount = 0; //循环接收数据 while (SerialPortManager.DicSerialPort[sp.PortName].serialPort.BytesToRead > 0) { SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[mReceiveByteCount] = (byte)SerialPortManager.DicSerialPort[sp.PortName].serialPort.ReadByte(); mReceiveByteCount = mReceiveByteCount + 1; //缓冲区溢出复位 if (mReceiveByteCount >= 1024) { mReceiveByteCount = 0; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 return; } } if (SerialPortManager.DicSerialPort[sp.PortName].SeriesType==SeriesTypeEnum.ModbusRTU)//RTU接受方式 { //输入寄存器 功能码0x04 if (mReceiveByteCount >= (WordLength * 2 + 5) && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1 && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[1] == 0x04) { mTempStr = ""; for (i = 0; i < (WordLength * 2 + 5); i++) { mTempStr = mTempStr + " " + SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[i].ToString("X2"); } SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } //保持寄存器 功能码0x03 if (mReceiveByteCount >= (WordLength * 2 + 5) && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1 && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[1] == 0x03) { mTempStr = ""; for (i = 0; i < (WordLength * 2 + 5); i++) { mTempStr = mTempStr + " " + SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[i].ToString("X2"); } //赋值给全局MW变量 从起始地址开始 int nDownPos; nDownPos = 0; for (i = 0; i < WordLength; i++) { SerialPortManager.DicSerialPort[sp.PortName].WordValueArray[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr, nDownPos] = (Int16)(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[3 + 2 * i] * 256 + SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[3 + 2 * i + 1]); nDownPos = nDownPos + 1; } SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } //输出线圈 功能码0x01 if (mReceiveByteCount >= (iBitLen + 5) && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1 && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[1] == 0x01) { mTempStr = ""; for (i = 0; i < (iBitLen + 5); i++) { mTempStr = mTempStr + " " + SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[i].ToString("X2"); } //赋值给全局变量 for (i = 0; i < SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[2]; i++) { ByteToBoolArray(SerialPortManager.DicSerialPort[sp.PortName],SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[3 + i], SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr, i * 8); } SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } //输入线圈 功能码0x02 if (mReceiveByteCount >= (iBitLen + 5) && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1 && SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[1] == 0x02) { mTempStr = ""; for (i = 0; i < (iBitLen + 5); i++) { mTempStr = mTempStr + " " + SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[i].ToString("X2"); } for (i = 0; i < SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[2]; i++) { ByteToBoolArray(SerialPortManager.DicSerialPort[sp.PortName],SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[3 + i], SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr, i * 8); } SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } } else //ASCII协议解析 { //保持寄存器 功能码0x03 string strTmpAddr, strTmpFun; strTmpAddr = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 1, 2); strTmpFun = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 3, 2); if (SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == ':' && mReceiveByteCount >= (WordLength * 4 + 11) && strTmpAddr == (SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1).ToString("X2") && strTmpFun == "03") { mTempStr = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 0, WordLength * 4 + 11); //赋值给全局MW变量 从起始地址开始 int nDownPos; nDownPos = 0; byte bTmpHi, bTmpLo; string tmpData; for (i = 0; i < WordLength; i++) { tmpData = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 7 + i * 4, 2); bTmpHi = Convert.ToByte(tmpData, 16); tmpData = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 9 + i * 4, 2); bTmpLo = Convert.ToByte(tmpData, 16); SerialPortManager.DicSerialPort[sp.PortName].WordValueArray[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr, nDownPos] = (Int16)(bTmpHi * 256 + bTmpLo); nDownPos = nDownPos + 1; } SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } //输入寄存器04 if (SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == ':' && mReceiveByteCount >= (WordLength * 4 + 11) && strTmpAddr == (SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1).ToString("X2") && strTmpFun == "04") { mTempStr = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 0, WordLength * 4 + 11); //赋值给全局MW变量 从起始地址开始 //int nDownPos; //nDownPos = 0; //byte bTmpHi, bTmpLo; //string tmpData; //for (i = 0; i < iMWordLen; i++) //{ // tmpData = System.Text.Encoding.ASCII.GetString(bData, 7 + i * 4, 2); // bTmpHi = Convert.ToByte(tmpData, 16); // tmpData = System.Text.Encoding.ASCII.GetString(bData, 9 + i * 4, 2); // bTmpLo = Convert.ToByte(tmpData, 16); // MWordVaue[CurrentAddr, nDownPos] = (UInt16)(bTmpHi * 256 + bTmpLo); // nDownPos = nDownPos + 1; //} SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } //输出线圈 功能码0x01 if (SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == ':' && mReceiveByteCount >= (iBitLen * 2 + 11) && strTmpAddr == (SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1).ToString("X2") && strTmpFun == "01") { byte bDataValue; string tmpData; mTempStr = ""; mTempStr = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 0, iBitLen * 2 + 11); //赋值给全局变量 for (i = 0; i < iBitLen; i++) { tmpData = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 7 + i * 2, 2); bDataValue = Convert.ToByte(tmpData, 16); ByteToBoolArray(SerialPortManager.DicSerialPort[sp.PortName], bDataValue, SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr, i * 8); } SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } //输入线圈 功能码0x02 if (SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData[0] == ':' && mReceiveByteCount >= (iBitLen * 2 + 11) && strTmpAddr == (SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr + 1).ToString("X2") && strTmpFun == "02") { //byte bDataValue; //string tmpData; mTempStr = ""; mTempStr = System.Text.Encoding.ASCII.GetString(SerialPortManager.DicSerialPort[sp.PortName].byteReceiveData, 0, iBitLen * 2 + 11); ////赋值给全局变量 //for (i = 0; i < iMBitLen; i++) //{ // tmpData = System.Text.Encoding.ASCII.GetString(bData, 7 + i * 2, 2); // bDataValue = Convert.ToByte(tmpData, 16); // ByteToBArray(bDataValue, CurrentAddr, i * 8); //} SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = mTempStr; SerialPortManager.DicSerialPort[sp.PortName].serialPort.DiscardInBuffer();//清输入缓冲区 SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = false;//通讯正常 SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//本次通讯结束 //bCommWell = true;//通讯GOOD } } } catch (Exception ex) { string str = "串口接收数据错误:"; Msg.Show($"{str}\r\n{ex}", $"{str}\r\nSerial port receiving data error:\r\n{ex}", $"{str}\r\nCổng nối tiếp nhận dữ liệu lỗi:\r\n{ex}", "Error", msgicon: MessageBoxIcon.Error); } } // MODBUS读保持寄存器 iAddress 开始地址(0开始),iLength 寄存器数量 //主站请求:01 03 00 00 00 06 70 08 //地址 1字节 //功能码 1字节 0x03 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 /// /// MODBUS读保持寄存器 /// /// 从站站号 /// 开始地址 /// 寄存器数量 public void ReadKeepReg(StSerialPort st, int iStation, long iAddress, int iLength, ref string str) { try { int i; iWordStartAddr = iAddress; WordLength = iLength; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250);//如果前一次接收没完成,则comBusing为true,则延时250ms byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x03; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); Crc16(SendCommand, 6); SendCommand[6] = CRCLo; SendCommand[7] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 8); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 8; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 Thread.Sleep(200); str = SerialPortManager.DicSerialPort[st.serialPort.PortName].strReceivCommandData; } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void ReadKeepRegAscii(StSerialPort st, int iStation, long iAddress, int iLength) { try { int i; string strLRC; string strSendCommand; iWordStartAddr = iAddress; WordLength = iLength; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x03; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); strSendCommand = ""; for (i = 0; i < 6; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // MODBUS读输入寄存器 iAddress 开始地址(0开始),iLength 寄存器数量 //主站请求:01 04 00 00 00 06 70 08 //地址 1字节 //功能码 1字节 0x04 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 /// /// MODBUS读输入寄存器(三菱PLC用不到) /// /// 从站站号 /// 开始地址 /// 寄存器数量 public void ReadInputReg(StSerialPort st, int iStation, long iAddress, int iLength) { try { int i; iWordStartAddr = iAddress; WordLength = iLength; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x04; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); Crc16(SendCommand, 6); SendCommand[6] = CRCLo; SendCommand[7] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 8); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 8; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void ReadInputRegAscii(StSerialPort st, int iStation, long iAddress, int iLength) { try { int i; string strLRC; string strSendCommand; iWordStartAddr = iAddress; WordLength = iLength; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x04; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); strSendCommand = ""; for (i = 0; i < 6; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // MODBUS读输出状态 iAddress 开始地址(0开始),iLength 输出位数量 //主站请求:01 01 00 00 00 07 70 08 //地址 1字节 //功能码 1字节 0x01 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 /// /// MODBUS读输出线圈状态 /// /// 从站站号 /// 开始地址 /// 输出位数量 public void ReadOutputStatus(StSerialPort st, int iStation, long iAddress, int iLength, ref string str) { try { int i; //一个字节代表8个位状态 //一个字节代表8个位状态 if (iLength % 8 == 0) { iBitLen = iLength / 8; } else { iBitLen = iLength / 8 + 1; } iBitStartAddr = iAddress; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x01; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); Crc16(SendCommand, 6); SendCommand[6] = CRCLo; SendCommand[7] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 8); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 8; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 Thread.Sleep(200); str = SerialPortManager.DicSerialPort[st.serialPort.PortName].strReceivCommandData; } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void ReadOutputStatusAscii(StSerialPort st, int iStation, long iAddress, int iLength) { try { int i; //一个字节代表8个位状态 //一个字节代表8个位状态 if (iLength % 8 == 0) { iBitLen = iLength / 8; } else { iBitLen = iLength / 8 + 1; } string strLRC; string strSendCommand; iBitStartAddr = iAddress; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x01; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); strSendCommand = ""; for (i = 0; i < 6; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // MODBUS读输入状态 iAddress 开始地址(0开始),iLength 输入位数量 //主站请求:01 02 00 00 00 07 70 08 //地址 1字节 //功能码 1字节 0x02 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 /// /// MODBUS读输入状态 /// /// 从站站号 /// 开始地址 /// 输入位数量 public void ReadInputStatus(StSerialPort st, int iStation, long iAddress, int iLength, ref string str) { try { int i; //一个字节代表8个位状态 //一个字节代表8个位状态 if (iLength % 8 == 0) { iBitLen = iLength / 8; } else { iBitLen = iLength / 8 + 1; } iBitStartAddr = iAddress; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x02; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); Crc16(SendCommand, 6); SendCommand[6] = CRCLo; SendCommand[7] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 8); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 8; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 Thread.Sleep(200); str = SerialPortManager.DicSerialPort[st.serialPort.PortName].strReceivCommandData; } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void ReadInputStatusAscii(StSerialPort st, int iStation, long iAddress, int iLength) { try { int i; //一个字节代表8个位状态 if (iLength % 8 == 0) { iBitLen = iLength / 8; } else { iBitLen = iLength / 8 + 1; } string strLRC; string strSendCommand; iBitStartAddr = iAddress; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x02; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((iLength - iLength % 256) / 256); SendCommand[5] = (byte)(iLength % 256); strSendCommand = ""; for (i = 0; i < 6; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // MODBUS强制单线圈 iAddress 开始地址(0开始) //主站请求:01 05 00 00 FF 00 70 08 //地址 1字节 //功能码 1字节 0x05 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 /// /// MODBUS强制单线圈 /// /// 从站站号 /// 开始地址 public void ForceOn_Circle(StSerialPort st, int iStation, long iAddress, ref string str) { try { int i; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x05; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = 0xff; SendCommand[5] = 0x00; Crc16(SendCommand, 6); SendCommand[6] = CRCLo; SendCommand[7] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 8); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 8; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 Thread.Sleep(200); str = SerialPortManager.DicSerialPort[st.serialPort.PortName].strReceivCommandData; } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void ForceOnAscii(StSerialPort st, int iStation, long iAddress) { try { int i; string strSendCommand, strLRC; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x05; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = 0xff; SendCommand[5] = 0x00; strSendCommand = ""; for (i = 0; i < 6; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; //System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // MODBUS复位单线圈 iAddress 开始地址(0开始) //主站请求:01 05 00 00 00 00 70 08 //地址 1字节 //功能码 1字节 0x05 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 public void ForceOff_Circle(StSerialPort st, int iStation, long iAddress, ref string str) { try { int i; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x05; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = 0x00; SendCommand[5] = 0x00; Crc16(SendCommand, 6); SendCommand[6] = CRCLo; SendCommand[7] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 8); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 8; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 Thread.Sleep(200); str = SerialPortManager.DicSerialPort[st.serialPort.PortName].strReceivCommandData; } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void ForceOffAscii(StSerialPort st, int iStation, long iAddress) { try { int i; string strSendCommand, strLRC; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x05; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = 0x00; SendCommand[5] = 0x00; strSendCommand = ""; for (i = 0; i < 6; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; //System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // MODBUS预置单字寄存器 iAddress 开始地址(0开始),iHiValue 数据 //主站请求:01 06 00 00 00 06 70 08 //地址 1字节 //功能码 1字节 0x06 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 /// /// MODBUS预置单字寄存器 /// /// 从站地址 /// 开始地址 /// 值 public void PreSetKeepReg(StSerialPort st, int iStation, long iAddress, UInt16 SetValue, ref string str) { try { int i; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x06; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((SetValue - SetValue % 256) / 256); ; SendCommand[5] = (byte)(SetValue % 256); ; Crc16(SendCommand, 6); SendCommand[6] = CRCLo; SendCommand[7] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 8); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 8; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 Thread.Sleep(200); str = SerialPortManager.DicSerialPort[st.serialPort.PortName].strReceivCommandData; } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void PreSetKeepRegAscii(StSerialPort st, int iStation, long iAddress, UInt16 SetValue) { try { int i; string strSendCommand, strLRC; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[8]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x06; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = (byte)((SetValue - SetValue % 256) / 256); ; SendCommand[5] = (byte)(SetValue % 256); ; strSendCommand = ""; for (i = 0; i < 6; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; //System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // MODBUS预置双字寄存器 iAddress 开始地址(0开始) //主站请求:01 06 00 00 00 10 70 08 //地址 1字节 //功能码 1字节 0x10 //起始寄存器地址 2字节 0x0000~0x0005 //寄存器数量 2字节 0x01~0x06 //CRC校验 2字节 /// /// MODBUS预置双字寄存器 /// /// 从站站号 /// 开始地址 /// 值 public void PreSetFloatKeepReg(StSerialPort st, int iStation, long iAddress, float SetValue, ref string str) { try { int i; byte[] bSetValue = new byte[4]; bSetValue = BitConverter.GetBytes(SetValue); //bSetValue = &SetValue; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[13]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x10; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = 0x00; SendCommand[5] = 0x02; SendCommand[6] = 0x04; SendCommand[7] = bSetValue[1]; SendCommand[8] = bSetValue[0]; SendCommand[9] = bSetValue[3]; SendCommand[10] = bSetValue[2]; Crc16(SendCommand, 11); SendCommand[11] = CRCLo; SendCommand[12] = CRCHi; //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(SendCommand, 0, 13); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = ""; for (i = 0; i < 13; i++) { SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData + " " + SendCommand[i].ToString("X2"); } tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 Thread.Sleep(200); str = SerialPortManager.DicSerialPort[st.serialPort.PortName].strReceivCommandData; } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void PreSetFloatKeepRegAscii(StSerialPort st, int iStation, long iAddress, float SetValue) { try { int i; string strSendCommand, strLRC; byte[] bSetValue = new byte[4]; bSetValue = BitConverter.GetBytes(SetValue); //bSetValue = &SetValue; iWordStartAddr = iAddress; //iMWordLen = 0; if (SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying == true) Thread.Sleep(250); byte[] SendCommand = new byte[13]; SerialPortManager.DicSerialPort[st.serialPort.PortName].CurrentAddr = iStation - 1; SendCommand[0] = (byte)iStation; SendCommand[1] = 0x10; SendCommand[2] = (byte)((iAddress - iAddress % 256) / 256); SendCommand[3] = (byte)(iAddress % 256); SendCommand[4] = 0x00; SendCommand[5] = 0x02; SendCommand[6] = 0x04; SendCommand[7] = bSetValue[1]; SendCommand[8] = bSetValue[0]; SendCommand[9] = bSetValue[3]; SendCommand[10] = bSetValue[2]; strSendCommand = ""; for (i = 0; i < 11; i++) { strSendCommand = strSendCommand + SendCommand[i].ToString("X2"); } strLRC = LRC(strSendCommand); strSendCommand = ":" + strSendCommand + strLRC; strSendCommand = strSendCommand + "\r" + "\n"; //System.Diagnostics.Trace.WriteLine(strSendCommand); //发送指令。 SerialPortManager.DicSerialPort[st.serialPort.PortName].serialPort.Write(strSendCommand); mReceiveByteCount = 0; //strUpData = ""; SerialPortManager.DicSerialPort[st.serialPort.PortName].strSendCommandData = strSendCommand; tmrTimeOut.Enabled = true;//启动超时检测定时器 SerialPortManager.DicSerialPort[st.serialPort.PortName].comBusying = true;//设置串口忙标志 //bCommWell = false;//设置本次通讯标志 } catch (Exception ex) { //strErrMsg = ex.Message.ToString(); MessageBox.Show($"串口发送数据错误:{ex.Message }", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //字节变量返回8为二进制字符串 /// /// 字节变量返回8位二进制字符串 /// /// 字节变量值 /// public string ByteToBinary(byte bValue) { string strTemp; int i, strLen; strTemp = System.Convert.ToString(bValue, 2); if (strTemp.Length < 8) { strLen = strTemp.Length; for (i = 0; i < 8 - strLen; i++) { strTemp = "0" + strTemp; } } return strTemp; } //字节变量赋值给bool型全局数组 /// /// 字节变量赋值给bool型全局数组 /// /// 字节变量值 /// 从站地址 /// 赋值开始数组索引值 public void ByteToBoolArray(StSerialPort st, byte bValue, int iAddr, int pos) { string strBinary; strBinary = ByteToBinary(bValue); for (int i = 0; i < 8; i++) { if (strBinary.Substring(7 - i, 1) == "1") { SerialPortManager.DicSerialPort[st.serialPort.PortName].BitVaueArray[iAddr, pos + i] = true; } else { SerialPortManager.DicSerialPort[st.serialPort.PortName].BitVaueArray[iAddr, pos + i] = false; } } } //定时器超时事件 public void commTimeOut(object source, System.Timers.ElapsedEventArgs e) { SerialPort sp = source as SerialPort; //if (bCommWell == false) { SerialPortManager.DicSerialPort[sp.PortName].bComRunNomalFlag[SerialPortManager.DicSerialPort[sp.PortName].CurrentAddr] = true;//设置本地址通讯故障 SerialPortManager.DicSerialPort[sp.PortName].strReceivCommandData = ""; } tmrTimeOut.Enabled = false; SerialPortManager.DicSerialPort[sp.PortName].comBusying = false;//设置串口忙标志 } } }