/// <summary> /// 设置通讯类的 命令打包工具 应该是从上层调用的类中指定的 /// </summary> /// <param name="DTPLCcmd"></param> public void SetDTPLCcmd(DTPLCPackCmdAndDataUnpack dtplccmd) { if (dtplccmd != null) { DTPLCcmd = dtplccmd; } }
public void SetDTPLCcmd(DTPLCPackCmdAndDataUnpack xjplccmd) { if (xjplccmd != null) { DTPLCcmd = xjplccmd; } }
public bool WriteMultiPleDMData(int relAddr, int[] value, string area, string mode) { int intArea = DTPLCPackCmdAndDataUnpack.AreaGetFromStr(area); List <int> mvalueLst = new List <int>(); if (intArea < Constant.M_ID) { if (mode.Equals(Constant.DoubleMode)) { int dcount = value.Count() * 2; List <int> valueLst = new List <int>(); foreach (int valuevaluesingle in value) { int addr_high = (int)((valuevaluesingle & 0xFFFF0000) >> 16); int addr_low = valuevaluesingle & 0xFFFF; valueLst.Add(addr_low); valueLst.Add(addr_high); } return(SetMultipleDArea(relAddr, dcount, valueLst.ToArray(), area)); } else { if (mode.Equals(Constant.SingleMode)) { return(SetMultipleDArea(relAddr, value.Count(), value, area)); } else { return(false); } } } else { string strvalue = ""; //8个数据一组 for (int i = 0; i < value.Count(); i++) { string s = value[i].ToString(); strvalue = strvalue.Insert(0, s); if ((((i + 1) % 8) == 0) || (i == value.Count() - 1)) { mvalueLst.Add(Convert.ToInt32(strvalue, 2)); strvalue = ""; } } } //这里传入的数据 应该是 return(SetMultipleMArea(relAddr, value.Count(), mvalueLst.ToArray(), area)); }
//传入相对地址 和区域 单双字 public DTPlcInfo(int addr, string areaIn, string valuemode) { this.relativeaddr = addr; this.StrArea = areaIn; absAddr = DTPLCPackCmdAndDataUnpack.AreaGetFromStr(relativeaddr, StrArea); intArea = DTPLCPackCmdAndDataUnpack.AreaGetFromStr(StrArea); valueMode = valuemode; //D区两个字节 if (intArea < Constant.M_ID) { ByteValue = new byte[2]; } else { ByteValue = new byte[1]; } }
/// <summary> /// XY 地址 8进制转换成十进制 进行类建立 /// </summary> /// <param name="addr"></param> /// <returns></returns> public DTPlcInfo[] GetPlcInfo(int addr, int count, string XYM, string mode) { List <DTPlcInfo> plcinforlst = new List <DTPlcInfo>(); int addrreal = addr; if (DTPLCPackCmdAndDataUnpack.AreaGetFromStr(XYM.Trim()) > Constant.HM_ID) { addrreal = ConstantMethod.GetXYAddr8To10(addr); } for (int i = 0; i < count; i++) { DTPlcInfo tmpInfo = new DTPlcInfo(addrreal, XYM.Trim(), mode); tmpInfo.Xuhao = -1; plcinforlst.Add(tmpInfo); addrreal++; } return(plcinforlst.ToArray()); }
public int PackSetCmdReadDDataOut(List <DTPlcInfo> addrLst) { List <byte> byteLst = new List <byte>(); List <byte> byteLstIn = new List <byte>(); List <byte> byteLstOut = new List <byte>(); byte[] DTCmdSetReadDDataOutTemp; byte[] DTCmdReadDDataOutTemp; DTCmdSetReadDDataOutTemp = Constant.DTCmdSetReadDDataOut232; DTCmdReadDDataOutTemp = Constant.DTCmdReadDDataOut232; if (ConnectMode == Constant.TaiDaConnectMode485) { DTCmdSetReadDDataOutTemp = Constant.DTCmdSetReadDDataOut485; DTCmdReadDDataOutTemp = Constant.DTCmdReadDDataOut485; } if (!(addrLst.Count > 0)) { CmdSetReadDDataOut = null; CmdSetReadDDataIn = null; CmdReadDDataOut = null; return(-1); } List <byte> cmdByte = new List <byte>(); for (int i = 0; i < addrLst.Count; i++) { int addr_high = (addrLst[i].AbsAddr & 0xFF00) >> 8; int addr_low = addrLst[i].AbsAddr & 0xFF; cmdByte.Add((byte)addr_high); cmdByte.Add((byte)addr_low); } int addrcount_high = ((addrLst.Count + 1) & 0xFF00) >> 8; int addrcount_low = (addrLst.Count + 1) & 0xFF; int count = (addrLst.Count + 1) * 2; //发送设置读取D区命令 byteLst.Add(0x01); byteLst.Add(0x10); byteLst.AddRange(DTCmdSetReadDDataOutTemp); byteLstIn.Add(0x01); byteLstIn.Add(0x10); byteLstIn.AddRange(DTCmdSetReadDDataOutTemp); byteLstOut.Add(0x01); byteLstOut.Add(0x03); byteLstOut.AddRange(DTCmdReadDDataOutTemp); int addrcount_high0 = ((addrLst.Count) & 0xFF00) >> 8; int addrcount_low0 = (addrLst.Count) & 0xFF; byteLstOut.Add((byte)addrcount_high0); byteLstOut.Add((byte)addrcount_low0); byteLst.Add((byte)addrcount_high); byteLst.Add((byte)addrcount_low); byteLstIn.Add((byte)addrcount_high); byteLstIn.Add((byte)addrcount_low); byteLst.Add((byte)((addrLst.Count + 1) * 2)); addrcount_high = ((addrLst.Count) & 0xFF00) >> 8; addrcount_low = (addrLst.Count) & 0xFF; byteLst.Add((byte)addrcount_high); byteLst.Add((byte)addrcount_low); byteLst.AddRange(cmdByte); //根据232 还是485来选择 byteLst.Add(DTPLCPackCmdAndDataUnpack.LRC16_C(byteLst.ToArray())); byteLstIn.Add(DTPLCPackCmdAndDataUnpack.LRC16_C(byteLstIn.ToArray())); byteLstOut.Add(DTPLCPackCmdAndDataUnpack.LRC16_C(byteLstOut.ToArray())); //开始拼接 台达设置读取D区命令 CmdSetReadDDataOut = byteLst.ToArray(); CmdSetReadDDataIn = byteLstIn.ToArray(); CmdReadDDataOut = byteLstOut.ToArray(); return(0); }
public int PackSetCmdReadMDataOut(List <List <DTPlcInfo> > addrLst) { List <DTPlcInfo> mplcLst = new List <DTPlcInfo>(); byte[] DTCmdSetReadMDataOutTemp; byte[] DTCmdReadMDataOutTemp; DTCmdSetReadMDataOutTemp = Constant.DTCmdSetReadMDataOut232; DTCmdReadMDataOutTemp = Constant.DTCmdReadMDataOut232; if (ConnectMode == Constant.TaiDaConnectMode485) { DTCmdSetReadMDataOutTemp = Constant.DTCmdSetReadMDataOut485; DTCmdReadMDataOutTemp = Constant.DTCmdReadMDataOut485; } for (int i = 0; i < addrLst.Count; i++) { mplcLst.AddRange(addrLst[i]); } if (!(mplcLst.Count > 0)) { CmdSetReadMDataOut = null; CmdSetReadMDataIn = null; CmdReadMDataOut = null; return(-1); } List <byte> cmdByte = new List <byte>(); for (int i = 0; i < mplcLst.Count; i++) { int addr_high = (mplcLst[i].AbsAddr & 0xFF00) >> 8; int addr_low = mplcLst[i].AbsAddr & 0xFF; cmdByte.Add((byte)addr_high); cmdByte.Add((byte)addr_low); } List <byte> byteLst = new List <byte>(); List <byte> byteLstIn = new List <byte>(); List <byte> byteLstOut = new List <byte>(); byteLst.Add(0x01); byteLst.Add(0x10); byteLst.AddRange(DTCmdSetReadMDataOutTemp); byteLstIn.Add(0x01); byteLstIn.Add(0x10); byteLstIn.AddRange(DTCmdSetReadMDataOutTemp); byteLstOut.Add(0x01); byteLstOut.Add(0x03); byteLstOut.AddRange(DTCmdReadMDataOutTemp); int addrcount_high = ((mplcLst.Count + 1) & 0xFF00) >> 8; int addrcount_low = (mplcLst.Count + 1) & 0xFF; int c = (int)Math.Ceiling((double)mplcLst.Count / 16); //多少个16位的数据 至少是16位 int addrcount_high0 = ((c) & 0xFF00) >> 8; int addrcount_low0 = (c) & 0xFF; int count = (mplcLst.Count + 1) * 2; byteLst.Add((byte)addrcount_high); byteLst.Add((byte)addrcount_low); byteLstIn.Add((byte)addrcount_high); byteLstIn.Add((byte)addrcount_low); byteLstOut.Add((byte)addrcount_high0); byteLstOut.Add((byte)addrcount_low0); byteLst.Add((byte)((mplcLst.Count + 1) * 2)); addrcount_high = ((mplcLst.Count) & 0xFF00) >> 8; addrcount_low = (mplcLst.Count) & 0xFF; byteLst.Add((byte)addrcount_high); byteLst.Add((byte)addrcount_low); byteLst.AddRange(cmdByte); byteLst.Add(DTPLCPackCmdAndDataUnpack.LRC16_C(byteLst.ToArray())); byteLstIn.Add(DTPLCPackCmdAndDataUnpack.LRC16_C(byteLstIn.ToArray())); byteLstOut.Add(DTPLCPackCmdAndDataUnpack.LRC16_C(byteLstOut.ToArray())); //开始拼接 台达设置读取D区命令 CmdSetReadMDataOut = byteLst.ToArray(); CmdSetReadMDataIn = byteLstIn.ToArray(); CmdReadMDataOut = byteLstOut.ToArray(); return(0); }
/// <summary> /// dataform中的数据 与 dplcinfo 和 mplcinfoall 集合对应起来 这样 更新速度会很快 /// </summary> /// <param name="datafm"></param> /// <param name="dAll"></param> /// <param name="mAll"></param> /// <returns></returns> private bool FindIndexInPlcInfo(DataTable datafm, List <DTPlcInfo> dAll, List <List <DTPlcInfo> > mAll) { foreach (DataRow row in datafm.Rows) { if (row == null) { continue; } int mAddr = 0; //地址 int mArea; string strSplit1; string strSplit2; //地址区域 string DSmode; //单字还是双字 strSplit1 = Regex.Replace(row["addr"].ToString().Trim(), "[A-Z]", "", RegexOptions.IgnoreCase); //取字母 strSplit2 = Regex.Replace(row["addr"].ToString().Trim(), "[0-9]", "", RegexOptions.IgnoreCase); strSplit1 = strSplit1.Trim(); strSplit2 = strSplit2.Trim(); DSmode = row["mode"].ToString().Trim(); //地址超了 无效 暂且定XDM 最大69999 if (!int.TryParse(strSplit1, out mAddr) || (mAddr < 0) || (mAddr > Constant.XJMaxAddr)) { continue; } int count; if (!int.TryParse(row["count"].ToString().Trim(), out count)) { continue; } mArea = DTPLCPackCmdAndDataUnpack.AreaGetFromStr(strSplit2); if (mArea > Constant.HM_ID) { mAddr = ConstantMethod.GetXYAddr8To10(mAddr); } mAddr = DTPLCPackCmdAndDataUnpack.AreaGetFromStr(mAddr, strSplit2); if (mArea < 0) { continue; } if (row["param1"] != null && row["param2"] != null) { int[] s = FindValueIndexFromDPlcInfo(mAddr, mArea, DSmode); row["param1"] = s[0]; row["param2"] = s[1]; //让集合 把dataform 也保存下 方便更新数据 if (mArea < Constant.M_ID) { if (!(s[0] > -1)) { continue; } DPlcInfo[s[0]].BelongToDT = datafm; DPlcInfo[s[0]].Row = datafm.Rows.IndexOf(row); } else { if (!(s[0] > -1 && s[1] > -1)) { continue; } MPlcInfoAll[s[0]][s[1]].BelongToDT = datafm; MPlcInfoAll[s[0]][s[1]].Row = datafm.Rows.IndexOf(row); } } } return(true); }
/// <summary> /// 这里增加一个 就是 主form太大了 分割一个form出来 但是 绑定 还是在原来那个主form上 /// </summary> /// <param name="dataForm0"></param> void SplitPackCmdReadDMDataOut(DataTable dataForm0, DataTable dataForm1) { List <DTPlcInfo> plcInfoLst = new List <DTPlcInfo>(); List <DTPlcInfo> MPlcInfo = new List <DTPlcInfo>(); foreach (DataRow row in dataForm0.Rows) { int mAddr = 0; int count = 0; string strSplit1; string strSplit2; string DSmode; //单字还是双字 #region 获取地址 个数 区域 创建plcinfo类 并添加到集合 if (row == null) { return; } if (row["addr"].ToString() == null || row["mode"].ToString() == null || row["count"].ToString() == null) { return; } ; //添加各个单元 //取数字 用替代的字符的方法 取数组就替换字母为空 取字母就替换数字 strSplit1 = Regex.Replace(row["addr"].ToString(), "[A-Z]", "", RegexOptions.IgnoreCase); //取字母 strSplit2 = Regex.Replace(row["addr"].ToString(), "[0-9]", "", RegexOptions.IgnoreCase); DSmode = row["mode"].ToString(); if (!int.TryParse(row["count"].ToString(), out count)) { continue; } //地址超了 无效 暂且定XDM 最大69999 if (!int.TryParse(strSplit1, out mAddr) || (mAddr < 0) || (mAddr > Constant.XJMaxAddr)) { continue; } //字母大于4 无效地址 if (strSplit2.Count() > 3) { continue; } //这里数组进行统计 if (DSmode.Equals(Constant.DoubleMode) && (DTPLCPackCmdAndDataUnpack.AreaGetFromStr(strSplit2) < Constant.M_ID)) { count = count * 2; } //传入数据起始地址 个数 区域 模式 DTPlcInfo[] tmpInfoLst = DTPLCcmd.GetPlcInfo(mAddr, count, strSplit2, DSmode); if (tmpInfoLst.Count() > 0) { plcInfoLst.AddRange(tmpInfoLst); } #endregion } #region 排序 去重复 统计DM 起始点 //排序 按照绝对地址 plcInfoLst = plcInfoLst.OrderBy(x => x.AbsAddr).ToList(); //去重复 plcInfoLst = plcInfoLst.Distinct(new ModelComparerDT()).ToList(); //分离D 区 M区 DPlcInfo = plcInfoLst.FindAll(t => t.IntArea < (Constant.HSD_ID + 1)); MPlcInfo = plcInfoLst.FindAll(t => t.IntArea > (Constant.HSD_ID)); DPlcInfo = InsertPlcInfo(DPlcInfo); //将D区分解出来 出来 变成一个一个单个的地址 尽量保持连续 MPlcInfo = InsertPlcInfo(MPlcInfo); plcInfoLst = DPlcInfo.Union(MPlcInfo).ToList <DTPlcInfo>(); #endregion #region 根据断点 建立命令的表格缓冲lst 然后创建读取DM区域的命令 //开始打包 List <int> addrLst = new List <int>(); //连续地址的起始地址 List <int> idLst = new List <int>(); //地址是D xy HSD List <int> addrcount = new List <int>(); //起始地址开始 读取几个寄存器 List <int> breakPoint = new List <int>(); //在 //首先要确定断点 breakPoint.Add(0); //获取不连续点的位置 D区域 for (int i = 0; i < plcInfoLst.Count - 1; i++) { if (((plcInfoLst[i + 1].RelAddr - plcInfoLst[i].RelAddr) > 1) || (plcInfoLst[i + 1].IntArea != plcInfoLst[i].IntArea)) { int bp = i + 1; breakPoint.Add(bp); } } breakPoint.Add(plcInfoLst.Count); //d区在前面,M区在后面 根据断点来区分 //统计D区起始地址个数 统计M区起始地址个数 //D区返回数据可以根据Dplcinfo集合来预算 //但M区需要知道M起始地址个数 for (int j = 0; j < breakPoint.Count; j++) { if (breakPoint[j] < plcInfoLst.Count) { addrLst.Add(plcInfoLst[breakPoint[j]].AbsAddr); idLst.Add(plcInfoLst[breakPoint[j]].IntArea); addrcount.Add(plcInfoLst[breakPoint[j + 1] - 1].RelAddr - plcInfoLst[breakPoint[j]].RelAddr + 1); } } //这里d区的话 需要指定一下双字情况下的 另外一个字节 FindHighPlcInfo(DPlcInfo); //这里M区麻烦一点 分成n个M单元组 每个单元组 有个起始地址 MPlcInfoAll = new List <List <DTPlcInfo> >(); for (int i = 0; i < addrLst.Count; i++) { List <DTPlcInfo> mplst = new List <DTPlcInfo>(); if (idLst[i] > Constant.HSD_ID) { for (int k = 0; k < addrcount[i]; k++) { DTPlcInfo p = new DTPlcInfo(); p.ValueMode = Constant.BitMode; p.ByteValue = new byte[1]; p.IntArea = idLst[i]; p.AbsAddr = addrLst[i] + k; p.Xuhao = k; mplst.Add(p); } } if (mplst.Count > 0) { MPlcInfoAll.Add(mplst); } } int mCount = 0; for (int i = 0; i < MPlcInfoAll.Count; i++) { double cntdb = (double)MPlcInfoAll[i].Count / 8; mCount = mCount + (int)Math.Ceiling(cntdb); } //绑定主form FindIndexInPlcInfo(dataForm1, DPlcInfo, MPlcInfoAll); DTPLCcmd.PackCmdReadDMDataOut(addrLst, idLst, addrcount, 5 + DPlcInfo.Count * 2 + mCount); #endregion addrLst = null; idLst = null; addrcount = null; breakPoint = null; //GC.Collect(); //GC.WaitForPendingFinalizers(); }
public DTDevice(List <string> filestr, int conneMode) { DTPLCcmd = new DTPLCPackCmdAndDataUnpack(); SetConnectMode(conneMode); Init(filestr); }
/// <summary> /// 针对信捷PLC 进行设备的存在获取 /// </summary> /// <returns></returns> public DTDevice(List <string> filestr) { DTPLCcmd = new DTPLCPackCmdAndDataUnpack(); Init(filestr); }
/// <summary> /// 串口数据接收 针对信台达PLC /// 数据没有结束符 只能通过校验来确认 /// 信捷PLC 通讯模式 发送一条带DM 区域的指令 返回所有数据 /// 数据错误需要超时机制来进行恢复 如果超时一定次数 则判断中断 机器不存在 // 数据长度达到 就进行数据处理判断 同时发送下一组读取命令 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void DTPLC_SerialPort_Received(object sender, SerialPortEvents e) { if (e.BufferData != null) { m_buffer.AddRange(e.BufferData); //返回命令统一都是0X3a开头 如果不是则移除 if (m_buffer[0] != Constant.DTHeader) { m_buffer.RemoveAt(0); } if ((m_buffer.Count > receivedByteCount)) { m_buffer.Clear(); } //收到数据就清空错误指示器,如果长时间通讯错误 肯定会一直往上加 ErrorConnCount = 0; #region 数据长度合格了 //数据接收超长了 也清空 数据刚好相等 头几个数据相同 if (m_buffer.Count == receivedByteCount) { //进行转换 去掉第一个0x3a m_buffer = ConstantMethod.DeltaBufferPro(m_buffer); //符合校验规则 if (DTPLCPackCmdAndDataUnpack.IsEnd(m_buffer.ToArray())) { if ((!isDeviceReady) && (ConstantMethod.compareByteStrictly(m_buffer.ToArray(), ConstantMethod.DeltaBufferPro(DTPLCcmd.CmdIn)))) { #region 设备未连接 //设备通了 要开始 连接了哦 准备好了 //设置标志位 打开监控定时器 设置发送和 接收命令 isDeviceReady = true; isGoToGetData = true; //台达这里还不能发送 因为要设置读取命令先 //SetCmdOutToCmdReadDMDataOut(); m_buffer.Clear(); #endregion } else { //设备连接情况下 是写数据区域命令的反馈 还是读数据区域命令的反馈 if (isWriteCmd) { #region 设备连接了 发送设置DM区域数据 //操做DTPLCcmd.CmdOut 只能在一条主线上做 不能再好多地方不然会出错 //这样 写寄存器的数据就要先放在一个缓存寄存命令里 SetCmdOutIn(DTPLCcmd.CmdSetBDREGOut, DTPLCcmd.CmdSetBDREGIn); if (ConstantMethod.compareByte(m_buffer.ToArray(), DTPLCcmd.CmdSetBDREGIn)) { isWriteCmd = false; //SetCmdOutToCmdReadDMDataOut(); } #endregion } else { #region 设置DM区域读取 这里不同于信捷 因为设置 命令返回还是要检查的 信捷直接就修改命令后 就返回数据了 所以多了个ympIsRePackymp if (IsSetReadDDataOut) { if (DTPLCcmd.CmdSetReadDDataOut != null) { SetCmdOutIn(DTPLCcmd.CmdSetReadDDataOut.ToArray(), DTPLCcmd.CmdSetReadDDataIn.ToArray()); if (ConstantMethod.compareByte(m_buffer.ToArray(), DTPLCcmd.CmdSetReadDDataIn)) { SetCmdDOut(DTPLCcmd.CmdReadDDataOut.ToArray()); IsSetReadDDataOut = false; IsSetReadMDataOut = true; IsReadingD = true; IsReadingM = false; } } else { IsSetReadDDataOut = false; IsSetReadMDataOut = true; } } else if (IsSetReadMDataOut) { if (DTPLCcmd.CmdSetReadMDataOut != null) { SetCmdOutIn(DTPLCcmd.CmdSetReadMDataOut.ToArray(), DTPLCcmd.CmdSetReadMDataIn.ToArray()); if (ConstantMethod.compareByte(m_buffer.ToArray(), DTPLCcmd.CmdSetReadMDataIn)) { SetCmdMOut(DTPLCcmd.CmdReadMDataOut.ToArray()); IsSetReadMDataOut = false; IsReadingM = true; IsReadingD = false; } } else { IsSetReadMDataOut = false; } } else #endregion //20180703249写到这里 #region 数据处理 //处理函数不为空 然后 数据开头也对 那就处理数据呗 if ((EventDataProcess != null)) { if (ConstantMethod.compareByte(m_buffer.ToArray(), Constant.DTReadDataCmdCheck)) { DataProcessEventArgs.Byte_buffer = m_buffer.ToArray(); EventDataProcess(this, DataProcessEventArgs); ConstantMethod.Delay(50); if ((IsReadingM) && (DTPLCcmd.CmdReadDDataOut != null)) { IsReadingD = true; IsReadingM = false; } else if ((IsReadingD) && (DTPLCcmd.CmdReadMDataOut != null)) { IsReadingM = true; IsReadingD = false; } } } #endregion } } } //在读的过程当中 如果遇到要写 那就先写 有没有在优化 if (IsGoToGetData && IsNoConnection == false) { if (!IsSetReadDDataOut && !IsSetReadMDataOut && !isWriteCmd) { if ((IsReadingM) && (DTPLCcmd.CmdReadMDataOut != null)) { SetCmdMOut(DTPLCcmd.CmdReadMDataOut); } else if ((IsReadingD) && (DTPLCcmd.CmdReadDDataOut != null)) { SetCmdDOut(DTPLCcmd.CmdReadDDataOut); } } m_SerialPortListener.Send(DTPLCcmd.CmdOut.ToArray()); } m_buffer.Clear(); #endregion 数据长度合格了 } else { //收到字节数超出预计长度了 if (m_buffer.Count > receivedByteCount) { m_buffer.Clear(); } } } ////GC.Collect(); ////GC.WaitForPendingFinalizers(); }