做上位機的同行應該有切實體會:由於某些廠家的通信協議不開放的緣故,通信是個很費勁的事,特別是和西門子的通信。就我目前所知,通信手段主要依賴於兩條路:
a.OPC,我們自己開發client端,server端借助simatic net 或者kepserver
b.組態軟件,組態軟件就不說了,稍微會點編程的人都不想用這東西。
OPC服務端和組態軟件都需要花錢購買(當然盜版除外),並且是一次性的,使用體驗感非常不爽,基於如此,我一直想找一個可替換的方案用於和PLC通信,經過多方面的探索驗證,終於找出一條不用經過任何中轉,借助socket完全用代碼實現的通信路徑,主要特征如下:
1.VS2015 C++ MFC開發
2.可實現和200,300,400,1500,1200對接通信(200沒測過)
3.可直接讀寫台達(ModBus)信息

1.台達指令示意
//*********************0F功能碼,寫多個位寄存器的值**********************************//
/*********************************************************************************/
//****00 00 00 00 00 08 01 0F A0 00 00 08 01 81********//
//**** 事務 | 協議 |Modbus數據長度|Modbus站號|功能碼|首地址|寫入個數|字節數| 值*******//
CString CDelta::WriteMoreRegistersBit(int FunNum, int Mod_Sta, int FristAds, int bitNum, int* pVal)
{
CString strModlen,//modbus數據長度
strFun,//功能碼
strMsta, //PLC站
strFristAds,//首地址
strWtbitnum,//寫入個數
strWtbytenum,//地址個數(字節)
strWtVal,//數值
strlabel;//指令
strModlen.Format(_T("%04X"), (int)ceil(bitNum /15.0) + 7);//modbus數據長度
strFun.Format(_T("%02X"), 15);
strMsta.Format(_T("%02X"), Mod_Sta);
strFristAds.Format(_T("%04X"), FristAds);
strlabel = _T("00 00 00 00 ") + strModlen + _T(" ") + strMsta + _T(" ") + strFun + _T(" ") + strFristAds;
strWtbitnum.Format(_T("%04X"), bitNum);
strWtbytenum.Format(_T("%02X"), (int)ceil(bitNum / 15.0));
strlabel = strlabel + _T(" ") + strWtbitnum + _T(" ") + strWtbytenum;
for (int i = 0; i < (int)ceil(bitNum / 15.0); i++)
{
strWtVal.Format(_T("%02X"), *(pVal + i));
strlabel += _T(" ") + strWtVal;
}
return strlabel;
}
2.西門子指令示意
/**01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31**/
/**03 00 00 1F 02 F0 80 32 01 00 00 00 01 00 0E 00 00 07 01 12 0A 10 02 00 02 00 0A 82 00 00 00**Y-output/
CString CSimatic::ReadRegXYBit(int seqnum, int Fun, int Rdlen, int DataType, int offset)//讀取X-input
{
CString strHead = _T("03 00"),
strtolen = _T("00 1F"),
strconst1 = _T("02 F0 80 32 01 00 00"),
strseqnum, //序列號
strconst2 = _T("00 0E"),
strconst3 = _T("00 00"),
strFun, //功能碼
strconst4 = _T("01 12 0A 10 02"),
strRdlen, //讀取長度
strDB = _T("00 00"),
strDataType, //訪問數據類型
stroffset;
strseqnum.Format(_T("%04X"), seqnum);
strFun.Format(_T("%02X"), Fun);
strRdlen.Format(_T("%04X"), Rdlen);
strDataType.Format(_T("%02X"), DataType);
stroffset.Format(_T("%06X"), offset);
CString strlabel;
strlabel = strHead + _T(" ") + strtolen + _T(" ") +
strconst1 + _T(" ") + strseqnum + _T(" ") +
strconst2 + _T(" ") + strconst3 + _T(" ") +
strFun + _T(" ") + strconst4 + _T(" ") +
strRdlen + _T(" ") + strDB + _T(" ") +
strDataType + _T(" ") + stroffset;
return strlabel;
}
試用版工具可免費試用,
有意者請訪問https://blog.csdn.net/li634471989/article/details/90291056,
或加q:634471989了解
