/// <summary> /// 写多个线圈和寄存器 /// </summary> /// <param name="devType">地址类型</param> /// <param name="regAddr">开始地址</param> /// <param name="wVal">多个值</param> /// <param name="er"></param> /// <returns></returns> public bool Write(int devAddr, int regAddr, int[] wVal, out string er) { er = string.Empty; try { int N = wVal.Length; //单写多个值 int rLen = 8; int wLen = N * 2; string wData = string.Empty; for (int i = 0; i < N; i++) { wData += wVal[i].ToString("X4"); } string wCmd = devAddr.ToString("X2"); wCmd += "11"; //寄存器功能码为0x10 -不保存EPROM 0x11->保存EPROM wCmd += regAddr.ToString("X4"); //开始地址 wCmd += N.ToString("X4"); //读地址长度 wCmd += wLen.ToString("X2"); //写入字节数 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 rLen = 8; if (devAddr == 0) { rLen = 0; } string rData = string.Empty; if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 检查CRC /// </summary> /// <param name="wCmd"></param> /// <returns></returns> private bool checkCRC(string wCmd) { string crc = CCRC.Crc16(wCmd.Substring(0, wCmd.Length - 4)); if (crc != wCmd.Substring(wCmd.Length - 4, 4)) { return(false); } return(true); }
/// <summary> /// 单写线圈和寄存器值 /// 从机地址(1Byte)+功能码(1Byte)+寄存器地址(2Byte)+地址数量(2Byte)+字节数(1Byte)+数据+CRC检验(2Byte) /// </summary> /// <param name="devType">地址类型</param> /// <param name="regAddr">开始地址</param> /// <param name="wVal">单个值</param> /// <param name="er"></param> /// <returns></returns> public bool Write(int devAddr, ERegType regType, int regAddr, int wVal, out string er) { er = string.Empty; try { int N = 1; //单写1个值 string wCmd = devAddr.ToString("X2"); int rLen = 0; int wLen = 0; string wData = string.Empty; if (regType != ERegType.D) { wCmd += "0F"; //线圈功能码为15 wLen = (7 + N) / 8; //写入字节数 rLen = 8; //回读长度 wData = wVal.ToString("X" + wLen * 2); } else { wCmd += "10"; //寄存器功能码为16 wLen = N * 2; //写入字节数 rLen = 8; //回读长度 wData = wVal.ToString("X" + wLen * 2); } wCmd += regAddr.ToString("X4"); //开始地址 wCmd += N.ToString("X4"); //读地址长度 wCmd += wLen.ToString("X2"); //写入字节数 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 string rData = string.Empty; rLen = 4; if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 读线圈 /// 从机地址(1Byte)+功能码(1Byte)+寄存器地址(2Byte)+地址数量(2Byte)+CRC检验(2Byte) /// </summary> /// <param name="devType">地址类型</param> /// <param name="regAddr">开始地址</param> /// <param name="N">地址长度</param> /// <param name="rData">16进制字符:数据值高位在前,低位在后</param> /// <param name="er"></param> /// <returns></returns> public bool Read(int devAddr, int regAddr, int N, out string rData, out string er) { rData = string.Empty; er = string.Empty; try { int rLen = N * 2; string wCmd = devAddr.ToString("X2"); wCmd += "03"; //寄存器功能码为03 wCmd += regAddr.ToString("X4"); //开始地址 wCmd += N.ToString("X4"); //读地址长度---1Byte wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 if (!com.send(wCmd, 5 + rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } string temp = rData.Substring(6, rLen * 2); rData = temp; //2个字节为寄存器值,高在前,低位在后,寄存器小排最前面; //转换为寄存器小排最后 rData = string.Empty; for (int i = 0; i < temp.Length / 4; i++) { rData = temp.Substring(i * 4, 4) + rData; } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 协议格式 /// </summary> /// <param name="wAddr"></param> /// <param name="wCmd"></param> /// <param name="wData"></param> /// <returns></returns> private string CalDataFromELCmd(int wAddr, string wCmd, string wData) { try { string cmd = string.Empty; int nLen = 1 + 1 + 2 + 1 + wData.Length / 2; cmd = SOI + wAddr.ToString("X2") + wCmd + nLen.ToString("X2") + wData; cmd += CCRC.Crc16(cmd); return(cmd); } catch (Exception ex) { return(ex.ToString()); } }
/// <summary> /// 单写线圈和寄存器值 /// 从机地址(1Byte)+功能码(1Byte)+寄存器地址(2Byte)+地址数量(2Byte)+字节数(1Byte)+数据+CRC检验(2Byte) /// </summary> /// <param name="devType">地址类型</param> /// <param name="regAddr">开始地址</param> /// <param name="wVal">单个值</param> /// <param name="er"></param> /// <returns></returns> public bool Write(int devAddr, int regAddr, int wVal, out string er) { er = string.Empty; try { int N = 1; //单写1个值 int wLen = N * 2; //写入字节数 string wData = wVal.ToString("X" + wLen * 2); int rLen = 4; //回读长度 string wCmd = string.Empty; wCmd = devAddr.ToString("X2"); //设备地址 wCmd += "10"; //寄存器功能码为16 wCmd += regAddr.ToString("X4"); //开始地址 wCmd += N.ToString("X4"); //地址长度 wCmd += wLen.ToString("X2"); //写入字节数 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 string rData = string.Empty; if (!com.send(wCmd, rLen, out rData, out er, _TimeOut)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 单写线圈和寄存器值 /// 从机地址(1Byte)+功能码(1Byte)+寄存器地址(2Byte)+地址数量(2Byte)+字节数(1Byte)+数据+CRC检验(2Byte) /// </summary> /// <param name="devType">地址类型</param> /// <param name="regAddr">开始地址</param> /// <param name="wVal">单个值</param> /// <param name="er"></param> /// <returns></returns> public bool Write(int devAddr, int regAddr, int wVal, out string er) { er = string.Empty; try { int N = 1; //单写1个值 int rLen = 8; //回读长度 int wLen = N * 2; string wData = string.Empty; wData = wVal.ToString("X" + wLen * 2); string wCmd = devAddr.ToString("X2"); //设备地址 wCmd += "07"; //寄存器功能码0x6 -不保存 EPROM 0x07->保存EPROM wCmd += regAddr.ToString("X4"); //开始地址 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 string rData = string.Empty; if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 检验和 /// </summary> /// <param name="wData"></param> /// <param name="er"></param> /// <returns></returns> private bool EL_CheckSum(string wData, out string er) { er = string.Empty; try { if (wData.Substring(0, 2) != SOI) { er = "数据桢头错误:" + wData; return(false); } if (wData.Length / 2 < 6) { er = "数据长度小于6:" + wData; return(false); } int rLen = System.Convert.ToInt16(wData.Substring(4, 2), 16); if ((wData.Length / 2) != (rLen + 2)) { er = "数据长度错误:" + wData; return(false); } string chkStr = wData.Substring(0, rLen * 2); string chkSum = wData.Substring(rLen * 2, 4); if (chkSum != CCRC.Crc16(chkStr)) { er = "数据CheckSum错误:" + wData; return(false); } if (wData.Substring(6, 2) != "01") { er = "返回数据确认FAIL:" + wData; return(false); } return(true); } catch (Exception ex) { er = ex.ToString(); return(false); } }
/// <summary> /// 复位机组并消音 /// </summary> /// <param name="devAddr"></param> /// <param name="er"></param> /// <returns></returns> public bool Reset(int devAddr, out string er) { er = string.Empty; try { string wCmd = devAddr.ToString("X2"); string rData = string.Empty; int regAddr = 8; int rLen = 8; wCmd += "05"; //寄存器功能码为05 wCmd += regAddr.ToString("X4"); //复位命令0008 wCmd += "FF00"; //有效命令FF00 无效命令0000 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = "crc16检验和错误:" + rData; return(false); } return(true); } catch (Exception ex) { er = ex.ToString(); return(false); } }
/// <summary> /// 复位机组并消音 /// </summary> /// <param name="devAddr"></param> /// <param name="er"></param> /// <returns></returns> public bool Reset(int devAddr, out string er) { er = string.Empty; try { string wCmd = devAddr.ToString("X2"); string rData = string.Empty; int rLen = 8; wCmd += "0F"; //寄存器功能码为0F wCmd += "00010002"; //开始地址 wCmd += "0103"; //命令 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = "crc16检验和错误:" + rData; return(false); } return(true); } catch (Exception ex) { er = ex.ToString(); return(false); } }
/// <summary> /// 单写寄存器值 /// 从机地址(1Byte)+功能码(1Byte)+寄存器地址(2Byte)+地址数量(2Byte)+字节数(1Byte)+数据+CRC检验(2Byte) /// </summary> /// <param name="devType">地址类型</param> /// <param name="startAddr">开始地址</param> /// <param name="wVal">单个值</param> /// <param name="er"></param> /// <returns></returns> public bool write(int devAddr, int startAddr, int wVal, out string er) { er = string.Empty; try { int N = 1; //单写1个值 string wCmd = devAddr.ToString("X2"); int rLen = 0; int wLen = 0; string wData = string.Empty; wCmd += "10"; //寄存器功能码为16 wLen = N * 2; //写入字节数 rLen = 8; //回读长度 wData = wVal.ToString("X" + wLen * 2); wCmd += formatDevAddr(startAddr); //开始地址 wCmd += N.ToString("X4"); //读地址长度 wCmd += wLen.ToString("X2"); //写入字节数 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 string rData = string.Empty; if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = "crc16检验和错误:" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 写多个线圈和寄存器 /// </summary> /// <param name="devType">地址类型</param> /// <param name="regAddr">开始地址</param> /// <param name="wVal">多个值</param> /// <param name="er"></param> /// <returns></returns> public bool Write(int devAddr, ERegType regType, int regAddr, int[] wVal, out string er) { er = string.Empty; try { int N = wVal.Length; //单写多个值 string wCmd = devAddr.ToString("X2"); int rLen = 0; int wLen = 0; string wData = string.Empty; if (regType != ERegType.D) { wCmd += "0F"; //线圈功能码为15 wLen = (7 + N) / 8; //写入字节数 rLen = 8; //回读长度 for (int i = 0; i < wLen; i++) { int val = 0; for (int j = 0; j < 8; j++) { if (i * 8 + j < N) { int bit = (wVal[i * 8 + j] & 0x1) << j; val += bit; } } wData += val.ToString("X2"); } } else { wCmd += "10"; //寄存器功能码为16 wLen = N * 2; //写入字节数 rLen = 8; //回读长度 for (int i = 0; i < N; i++) { wData += wVal[i].ToString("X4"); } } wCmd += regAddr.ToString("X4"); //开始地址 wCmd += N.ToString("X4"); //读地址长度 wCmd += wLen.ToString("X2"); //写入字节数 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 rLen = 4; string rData = string.Empty; if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 读线圈 /// 从机地址(1Byte)+功能码(1Byte)+寄存器地址(2Byte)+地址数量(2Byte)+CRC检验(2Byte) /// </summary> /// <param name="devType">地址类型</param> /// <param name="regAddr">开始地址</param> /// <param name="N">地址长度</param> /// <param name="rData">16进制字符:数据值高位在前,低位在后</param> /// <param name="er"></param> /// <returns></returns> public bool Read(int devAddr, ERegType regType, int regAddr, int N, out string rData, out string er) { rData = string.Empty; er = string.Empty; try { string wCmd = devAddr.ToString("X2"); int rLen = 0; if (regType != ERegType.D) { wCmd += "01"; //线圈功能码为01 rLen = (N + 7) / 8; //8个线圈为1Byte:前8个线圈存第1字节,最小线圈存最低位 } else { wCmd += "03"; //寄存器功能码为03 rLen = N * 2; } wCmd += regAddr.ToString("X4"); //开始地址 wCmd += N.ToString("X2"); //读地址长度---1Byte wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 if (!com.send(wCmd, 5 + rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } string temp = rData.Substring(6, rLen * 2); if (regType != ERegType.D) { //转化线圈数据为 Mn,Mn-1..M1,M0(高位在前,低位在后) string coil_HL = string.Empty; int coilLen = temp.Length / 2; for (int i = 0; i < coilLen; i++) { coil_HL += temp.Substring(temp.Length - (i + 1) * 2, 2); } rData = coil_HL; } else { rData = temp; //2个字节为寄存器值,高在前,低位在后,寄存器小排最前面; //转换为寄存器小排最后 rData = string.Empty; for (int i = 0; i < temp.Length / 4; i++) { rData = temp.Substring(i * 4, 4) + rData; } } return(true); } catch (Exception e) { er = e.ToString(); return(false); } }
/// <summary> /// 写多线圈和寄存器值 /// </summary> /// <param name="plcAddr">PLC地址</param> /// <param name="regType">寄存器类型</param> /// <param name="startAddr">开始地址</param> /// <param name="N">双字节(FFFF)为1个长度</param> /// <param name="strHex">16进制字符格式:FFFF FFFF(N=2) 高4位在前,低4位在后</param> /// <param name="er"></param> /// <returns></returns> public bool Write(int plcAddr, ERegType regType, int startAddr, int N, string strHexVal, out string er) { lock (_sync) { try { //N:单写1个值 --->双字节0xFFFF --->word字节0xFFFFFFFF string wCmd = plcAddr.ToString("X2"); int rLen = 0; int wLen = 0; string wData = string.Empty; if (regType != ERegType.D) { wCmd += "0F"; //线圈功能码为15 wLen = (7 + N) / 8; //写入字节数 rLen = 8; //回读长度 } else { wCmd += "10"; //寄存器功能码为16 wLen = N * 2; //写入字节数 rLen = 8; //回读长度 } //反转:低位在前,高位在后 for (int i = 0; i < N; i++) { wData += "0000"; } string temp = string.Empty; for (int i = 0; i < strHexVal.Length / 4; i++) { temp = strHexVal.Substring(i * 4, 4) + temp; } wData = wData + temp; wData = wData.Substring(wData.Length - wLen * 2, wLen * 2); wCmd += formatDevAddr(regType, startAddr); //开始地址 wCmd += N.ToString("X4"); //读地址长度 wCmd += wLen.ToString("X2"); //写入字节数 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 string rData = string.Empty; if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } } }
/// <summary> /// 空调温度 /// </summary> /// <param name="devAddr"></param> /// <param name="rData"></param> /// <param name="er"></param> /// <returns></returns> public bool AirTemp(int devAddr, out double[] rTemp, out string er) { er = string.Empty; rTemp = new double[2]; bool bSta = true; try { for (int i = 0; i < 2; i++) { string wCmd = devAddr.ToString("X2"); string rData = string.Empty; long regAddr = 0x170A + i; int rLen = 7; wCmd += "04"; //寄存器功能码为04 wCmd += Convert.ToString(regAddr, 16); wCmd += "0001"; wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = "crc16检验和错误:" + rData; return(false); } rData = rData.Substring(6, 4); switch (rData) { case "8041": rData = string.Empty; er += "探头[" + (i + 1).ToString() + "]短路;"; break; case "8042": rData = string.Empty; er += "探头[" + (i + 1).ToString() + "]断路;"; break; case "8043": rData = string.Empty; er += "探头[" + (i + 1).ToString() + "]故障;"; break; case "8044": rData = string.Empty; er += "探头[" + (i + 1).ToString() + "]不存在;"; break; default: rTemp[i] = (double)Convert.ToInt32(rData, 16) / 10; break; } if (rData == "") { bSta = false; } } return(bSta); } catch (Exception ex) { er = ex.ToString(); return(false); } }
/// <summary> /// 运行状态 /// </summary> /// <param name="devAddr"></param> /// <param name="rData">0:待机 1:启动中 2:运行中 3:停机中 4:严重故障 5:防冻</param> /// <param name="er"></param> /// <returns></returns> public bool RunState(int devAddr, out string rData, out string er) { er = string.Empty; rData = string.Empty; try { string wCmd = devAddr.ToString("X2"); int rLen = 7; wCmd += "04"; //寄存器功能码为05 wCmd += "17000001"; wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = "crc16检验和错误:" + rData; return(false); } rData = rData.Substring(6, 4); switch (rData) { case "0000": rData = "待机中"; break; case "0001": rData = "启动中"; break; case "0002": rData = "运行中"; break; case "0003": rData = "停机中"; break; case "0004": rData = "严重故障"; break; case "0005": rData = "防冻"; break; default: break; } return(true); } catch (Exception ex) { er = ex.ToString(); return(false); } }
/// <summary> /// 单写线圈和寄存器值 /// </summary> /// <param name="plcAddr">PLC地址</param> /// <param name="regType">寄存器类型</param> /// <param name="startAddr">开始地址</param> /// <param name="startBin">0</param> /// <param name="wVal">数据值</param> /// <param name="er"></param> /// <returns></returns> public bool Write(int plcAddr, ERegType regType, int startAddr, int startBit, int wVal, out string er) { lock (_sync) { er = string.Empty; try { int N = 1; //单写1个值 if (startBit > 0) { N = startBit; } string wCmd = plcAddr.ToString("X2"); int rLen = 0; int wLen = 0; string wData = string.Empty; if (regType != ERegType.D) { wCmd += "0F"; //线圈功能码为15 wLen = (7 + N) / 8; //写入字节数 rLen = 8; //回读长度 wData = wVal.ToString("X" + wLen * 2); } else { wCmd += "10"; //寄存器功能码为16 wLen = N * 2; //写入字节数 rLen = 8; //回读长度 wData = wVal.ToString("X" + wLen * 2); string temp = wData; wData = string.Empty; for (int i = 0; i < temp.Length / 4; i++) { wData = temp.Substring(i * 4, 4) + wData; } } wCmd += formatDevAddr(regType, startAddr); //开始地址 wCmd += N.ToString("X4"); //读地址长度 wCmd += wLen.ToString("X2"); //写入字节数 wCmd += wData; //写入数据 wCmd += CCRC.Crc16(wCmd); //CRC16 低位前,高位后 string rData = string.Empty; if (!com.send(wCmd, rLen, out rData, out er)) { return(false); } if (!checkCRC(rData)) { er = CLanguage.Lan("crc16检验和错误") + ":" + rData; return(false); } return(true); } catch (Exception e) { er = e.ToString(); return(false); } } }