三菱PLC串口通信開(kāi)發(fā)心得經(jīng)驗(yàn)

發(fā)布時(shí)間:2024-03-03
記得兩年前剛開(kāi)始從事軟件開(kāi)發(fā)工作時(shí),第一份任務(wù)就是開(kāi)發(fā)一個(gè)程序能夠?qū)崿F(xiàn)與三菱plc 串口通信。所謂通信,其實(shí)質(zhì)主要是對(duì)plc 的d寄存器(dword)讀寫操作。但是因?yàn)槿毡緸榱吮Wo(hù)其產(chǎn)品,并不開(kāi)發(fā)串口通信協(xié)議。在不開(kāi)發(fā)通信協(xié)議的情況,如果想實(shí)現(xiàn)通信,首先需要做的便是通過(guò)數(shù)據(jù)分析,破解其通信協(xié)議。這里就不講解如何破解了,主要是介紹下當(dāng)時(shí)博主開(kāi)發(fā)程序的背景。
小編寫這篇文章的主要目的是為了分享過(guò)去自己的開(kāi)發(fā)經(jīng)驗(yàn),因?yàn)樽约涸陂_(kāi)發(fā)的過(guò)程中曾經(jīng)接受過(guò)很多開(kāi)源軟件的幫助,現(xiàn)在這是轉(zhuǎn)入正題。
涉及字節(jié)流數(shù)據(jù)通信,必然要涉及通信協(xié)議。鑒于當(dāng)時(shí)的開(kāi)發(fā)需求,博主僅對(duì)d寄存器的讀寫協(xié)議分析過(guò)。其他寄存器理論上是相似,有興趣的同學(xué)可以自行分析數(shù)據(jù)進(jìn)行測(cè)試。
d寄存器的通信協(xié)議相對(duì)比較簡(jiǎn)單,主要可以分為:
1.問(wèn)候應(yīng)答協(xié)議
2.狀態(tài)查詢協(xié)議
3.狀態(tài)配置協(xié)議
4.數(shù)據(jù)反饋協(xié)議
在plc通信過(guò)程中主要的三個(gè)難點(diǎn)在于寄存器的加密解密,數(shù)據(jù)信息加密和解密,以及字符的校驗(yàn)。
寄存器地址加密過(guò)程:
《span style=“font-size:18px;”》void plc_dataparse::encrypt_toplcaddress( byte *parray , const uint paddress )
{
int encode_address = 0x1000 + paddress * 2;
byte encrypt_key = encode_address & 0xf;
parray[3] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
encrypt_key = (encode_address 》》 4) & 0xf;
parray[2] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
encrypt_key = (encode_address 》》 8) & 0xf;
parray[1] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
encrypt_key = (encode_address 》》 12) & 0xf;
parray[0] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
}
《/span》
數(shù)據(jù)信息的加密過(guò)程:
《span style=“font-size:18px;”》void plc_dataparse::encrypt_toplccontent( byte * parray , const uint pcontent )
{
byte encrypt_key = pcontent & 0xf;
parray[1] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
encrypt_key = (pcontent 》》 4) & 0xf;
parray[0] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
encrypt_key = (pcontent 》》 8) & 0xf;
parray[3] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
encrypt_key = (pcontent 》》 12) & 0xf;
parray[2] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
}
《/span》
添加校驗(yàn)碼:
《span style=“font-size:18px;”》void plc_dataparse::add_checkcode( byte * pdest , byte * psrc , const uint plenth )
{
int sumtemp = 0;
for ( unsigned int i = 0; i《 plenth; i++)
{
sumtemp += (*(psrc + i));
}
byte encrypt_key = sumtemp & 0xf; // get low 4 bit
pdest[1] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
encrypt_key = (sumtemp 》》 4) & 0xf; // get high 4 bit
pdest[0] = (encrypt_key《10) ? (encrypt_key + 0x30) : (encrypt_key + 0x41 - 0xa);
}
《/span》
提取數(shù)據(jù)信息:
《span style=“font-size:18px;”》double plc_dataparse::get_content( byte *parray , uint plenth )
{
byte dl_data[4];
byte pre_data[4];
double pow_numb;
for (int j = 0; j《4; j++) //剔除雜碼
{
pre_data[j] = parray[j + 1];
}
//////////////////////////////////////////////////////////////////////////
dl_data[1] = (pre_data[0]《0x40) ? (pre_data[0] - 0x30) : (pre_data[0] - 0x41 + 0x0a);
dl_data[0] = (pre_data[1]《0x40) ? (pre_data[1] - 0x30) : (pre_data[1] - 0x41 + 0x0a);
dl_data[3] = (pre_data[2]《0x40) ? (pre_data[2] - 0x30) : (pre_data[2] - 0x41 + 0x0a);
dl_data[2] = (pre_data[3]《0x40) ? (pre_data[3] - 0x30) : (pre_data[3] - 0x41 + 0x0a);
for (int i = 0; i《4; i++)
{
dl_data[i] = dl_data[i] & 0xf;
}
pow_numb = dl_data[3] * pow(16.0, 3.0) + dl_data[2] * pow(16.0, 2.0) + dl_data[1] * 16 + dl_data[0];
return pow_numb;
}
《/span》
校驗(yàn)接受數(shù)據(jù)校驗(yàn)碼:
int plc_dataparse::check_checkcode( byte *parray , uint plenth )
{
int error_code = plc_success;
const int legal_lenth = 8; //the define legal lenth
if (plenth != legal_lenth)
{
error_code = plc_crcerror;
return error_code;
}
//////////////////////////////////////////////////////////////////////////
//check code
else
{
byte *pbyte = new byte[2];
// split out head mark , tail check out
add_checkcode(&pbyte[0], &parray[1], plenth - 3); //calculate the check code
for (int j = 0; j《2; j++)
{
if (pbyte[j] != parray[plenth - 2 + j])
{
error_code = plc_crcerror;
break;
}
}
// release the pointer and it‘s stack
delete pbyte;
pbyte = null;
return error_code;
}
}
上述代碼是使用plc窗口通信的最大的難點(diǎn)。一旦掌握幾大難點(diǎn),基本plc的串口通信就很簡(jiǎn)單了。
另附上一份當(dāng)時(shí)自己開(kāi)發(fā)的三菱plcd寄存器調(diào)試程序。
備注:該調(diào)試工具僅支持xp系統(tǒng)
上一個(gè):怎么阻止手機(jī)軟件彈廣告,手機(jī)會(huì)自動(dòng)彈出廣告窗口如何徹底關(guān)閉
下一個(gè):大口徑水表遠(yuǎn)傳監(jiān)控設(shè)備

硬糖社區(qū)怎么發(fā),qq社區(qū)怎么進(jìn)
內(nèi)存卡安裝不上怎么辦,手機(jī)內(nèi)存卡壞了換了個(gè)新的安裝不了東西怎么辦
毛萼香茶菜清熱利咽片
pad能給電腦充電嗎-(用電腦充電器給ipad充電)
電腦鍵盤打字圖解
供應(yīng)橡塑保溫板優(yōu)惠廠家
暖通施工紅燈區(qū),這些“套路”你得會(huì)!
電腦安裝系統(tǒng)u盤要多大內(nèi)存(裝系統(tǒng)的u盤需要多少g)
商務(wù)筆記本電腦選哪款好,商務(wù)本筆記本電腦推薦
電腦win7怎么升級(jí)到win10系統(tǒng)(電腦win7怎么升級(jí)到win10文件還有嗎)
十八禁 网站在线观看免费视频_2020av天堂网_一 级 黄 色 片免费网站_绝顶高潮合集Videos