文章目录
- 前言
- 一、HOSTLINK协议说明
- 二、校验码(FCS)计算
- 三、示例完整代码
- 四、下载链接
- 总结
前言
本文讲述了Qt下模拟串口调试工具发送HOSTLINK(FINS)模式,主要进行了HR保持区的字和位的读写,对HOSTLINK协议中校验码(FCS)的计算方式进行了展示,详情可见下文代码,希望可以帮助到大家,如有错误之处,欢迎大家批评指正。
项目效果
提示:以下是本篇文章正文内容,下面案例可供参考
一、HOSTLINK协议说明
HOSTLINK(FINS)命令细化的格式内容如下图所示
这里对FINS的命令格式进行解释(详细内容可见说明书)
(a)、command code(命令代码)
0101 :读命令
0102 :写命令
(b)、IO Memory Area Code(内存区域地址)
WR(Word):B1
WR(Bit):31
HR(Word):B2
HR(Bit):32
… …
此处以示例来进行上述格式说明:
//单写HR字地址(HR1写入数据1) 写:0102 字:B2
@ 00 FA 0 00 00 00 00 0102 B2 00 01(address) 00 00 01 0001(data) **(FCS) *\CR
//单读HR字地址(读取HR1地址上的数值) 读:0101 字:B2
@ 00 FA 0 00 00 00 00 0101 B2 00 01(address) 00 00 01 **(FCS) *\CR
//单写HR位地址(对HR1.01位写入数据1) 写:0102 位:32
@ 00 FA 0 00 00 00 00 0102 32 00 0101(address) 00 01 01(data) **(FCS) *\CR
//单读HR位地址(读取HR1.01位上的数值) 读:0101 位:32
@ 00 FA 0 00 00 00 00 0101 32 00 0101(address) 00 01 **(FCS) *\CR
二、校验码(FCS)计算
协议中FCS栏位:占用两个字符,取值为从@开始到正文结束的所有字符的ASCⅡ码按位异或运算的结果。计算校验码的步骤:
1.先进行输入地址位的转换
2.界面上显示的是ASCII字符,将界面上字符转化为十进制后进行按位异或运算
3.按位运算后的结果转换为16进制即为校验码
三、示例完整代码
1.示例中用到了串口相关函数,所以需要在pro中添加下列代码:
QT += serialport
2.serialport.h
#ifndef SERIALPORT_H
#define SERIALPORT_H
#include <QWidget>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class SerialPort; }
QT_END_NAMESPACE
class SerialPort : public QWidget
{
Q_OBJECT
public:
SerialPort(QWidget *parent = nullptr);
~SerialPort();
void initWidget();
private slots:
void slot_serialRead();
void slot_writeHRWordData(int address, int numWrite);
void slot_readHRWordData(int address);
void slot_writeHRBitData(int address, int bit, int numWrite);
void slot_readHRBitData(int address, int bit);
void on_pb_refresh_clicked();
void on_pb_operate_clicked();
void on_pb_send_clicked();
void on_rb_read_clicked();
void on_rb_write_clicked();
private:
Ui::SerialPort *ui;
QSerialPort *serial;
};
#endif // SERIALPORT_H
3.serialport.cpp
#include "serialport.h"
#include "ui_serialport.h"
SerialPort::SerialPort(QWidget *parent)
: QWidget(parent)
, ui(new Ui::SerialPort)
{
ui->setupUi(this);
this->initWidget();
}
SerialPort::~SerialPort()
{
delete ui;
}
void SerialPort::initWidget()
{
this->setWindowTitle("HOSTLINK(FINS)读写测试");
setFixedSize(this->width(),this->height());
ui->rb_read->setChecked(true);
ui->le_num->setEnabled(false);
ui->pb_send->setEnabled(false);
//初始化串口
serial = new QSerialPort(this);
connect(serial,SIGNAL(readyRead()),this,SLOT(slot_serialRead()));
}
void SerialPort::slot_serialRead()
{
QByteArray receiveBuf = serial->readAll();
QString receiveStr = QString(receiveBuf);
//qDebug()<<"receiveStr:"<<receiveStr;
int sizeNum = receiveStr.size();
QString showStr = receiveStr.left(sizeNum - 1);
ui->plainTextEdit->appendPlainText("接收命令:\n" + showStr + "\\CR");
QString leftStr = receiveStr.left(sizeNum - 4);
//qDebug()<<"leftStr:"<<leftStr;
QString rightStr = leftStr.right(sizeNum - 4 - 23);
//qDebug()<<"receiveStr:"<<receiveStr<<" leftStr:"<<leftStr<<" rightStr:"<<rightStr;
//rightStr需要视情况而定
ui->le_num->setText(rightStr);
}
//单写HR字地址
void SerialPort::slot_writeHRWordData(int address,int numWrite)
{
//H保持区 字:B2 位:32
//@ 00 FA 0 00 00 00 00 0102 B2 00 01(address) 00 00 01 0001(data) **(FCS) *\CR
//QString testStr = "@00FA0000000000102B200010000010001";
//address
QString startStr = "@00FA0000000000102B200";
int adsNum[2];
QByteArray hrBa;
hrBa.setNum(address,16);
if(address < 16)
{
adsNum[0] = 0;
adsNum[1] = address;
startStr.append("0" + QString(hrBa) + "000001");
}
else
{
adsNum[0] = (int)hrBa.at(0);
adsNum[1] = (int)hrBa.at(1);
startStr.append(QString(hrBa) + "000001");
}
//qDebug()<<"num[0]:"<<num[0]<<" num[1]:"<<num[1];
//numWrite 根据写入值长度变化
#if 0
QString numStr = QString::number(numWrite);
QByteArray numBa = numStr.toLatin1();
qDebug()<<"numBa:"<<numBa;
int numSize = numStr.size();
int numEnd = numSize;
//qDebug()<<"numSize:"<<numSize;
if(numSize%2)
{
numEnd = numSize + 1;
}
//qDebug()<<"numEnd:"<<numEnd;
int numNum[numEnd];
if(numSize%2)
{
numNum[0] = 0;
for(int i=1;i<numEnd;i++)
{
numNum[i] = (int)numBa.at(i-1);
}
startStr.append("0" + QString(numBa));
}
else
{
for(int i=0;i<numEnd;i++)
{
numNum[i] = (int)numBa.at(i);
}
startStr.append(QString(numBa));
}
#else
QString finStr = "";
QString numStr = QString::number(numWrite);
int numSize = numStr.size();
if(numSize < 4)
{
for(int i=numSize;i<4;i++)
{
finStr.append("0");
}
finStr += numStr;
}
else if(numSize == 4)
{
finStr = numStr;
}
else if(numSize == 5)
{
finStr = "0" + numStr;
}
else if(numSize == 6)
{
finStr = numStr;
}
else
{
finStr = "0000";
}
QByteArray numBa = finStr.toLatin1();
//qDebug()<<"numBa:"<<numBa;
int numEnd = finStr.size();
//qDebug()<<"numEnd:"<<numEnd;
int numNum[numEnd];
for(int i=0;i<numEnd;i++)
{
numNum[i] = (int)numBa.at(i);
}
startStr.append(QString(numBa));
#endif
quint8 sendBuf[30+numEnd];
memset(sendBuf+numEnd,0,30+numEnd);
sendBuf[0] = (quint8)0x40; //@ 64
sendBuf[1] = (quint8)0x30; //0 48
sendBuf[2] = (quint8)0x30; //0 48
sendBuf[3] = (quint8)0x46; //F 70
sendBuf[4] = (quint8)0x41; //A 65
sendBuf[5] = (quint8)0x30; //0 48
sendBuf[6] = (quint8)0x30; //0 48
sendBuf[7] = (quint8)0x30; //0 48
sendBuf[8] = (quint8)0x30; //0 48
sendBuf[9] = (quint8)0x30; //0 48
sendBuf[10] = (quint8)0x30; //0 48
sendBuf[11] = (quint8)0x30; //0 48
sendBuf[12] = (quint8)0x30; //0 48
sendBuf[13] = (quint8)0x30; //0 48
sendBuf[14] = (quint8)0x30; //0 48
sendBuf[15] = (quint8)0x31; //1 49
sendBuf[16] = (quint8)0x30; //0 48
sendBuf[17] = (quint8)0x32; //2 50
sendBuf[18] = (quint8)0x42; //B 66
sendBuf[19] = (quint8)0x32; //2 50
sendBuf[20] = (quint8)0x30; //0 48
sendBuf[21] = (quint8)0x30; //0 48
sendBuf[22] = (quint8)adsNum[0]; //0 48
sendBuf[23] = (quint8)adsNum[1]; //1 49
sendBuf[24] = (quint8)0x30; //0 48
sendBuf[25] = (quint8)0x30; //0 48
sendBuf[26] = (quint8)0x30; //0 48
sendBuf[27] = (quint8)0x30; //0 48
sendBuf[28] = (quint8)0x30; //0 48
sendBuf[29] = (quint8)0x31; //1 49
for(int i=0;i<numEnd;i++) //data 1234
{
sendBuf[30+i] = numNum[i];
}
quint8 fcsNum = 0;
for(int i=0;i<30+numEnd;i++)
{
fcsNum ^= sendBuf[i];
}
QByteArray fcsBa;
fcsBa.setNum(fcsNum,16);
//qDebug()<<"fcsBa:"<<fcsBa;
QString scsStr = "";
if(fcsBa.size() == 1)
{
scsStr = "0" + QString(fcsBa);
}
else
{
scsStr = QString(fcsBa);
}
//qDebug()<<"ab:"<<ab;
startStr.append(scsStr + "*\r");
QString lastStr = startStr.toUpper();
//qDebug()<<"lastStr:"<<lastStr;
int sizeNum = lastStr.size();
QString showStr = lastStr.left(sizeNum - 1);
ui->plainTextEdit->appendPlainText("发送写命令:\n" + showStr + "\\CR");
char *writeStr;
QByteArray writeBa = lastStr.toLatin1();
writeStr = writeBa.data();
qDebug()<<"writeStr:"<<writeStr;
serial->write(writeStr);
}
//单读HR字地址
void SerialPort::slot_readHRWordData(int address)
{
//H保持区 字:B2 位:32
//@ 00 FA 0 00 00 00 00 0101 B2 00 01(address) 00 00 01 **(FCS) *\CR
//QString testStr = "@00FA0000000000101B20001000001";
QString startStr = "@00FA0000000000101B200";
//address
int adsNum[2];
QByteArray hrBa;
hrBa.setNum(address,16);
if(address < 16)
{
adsNum[0] = 0;
adsNum[1] = address;
startStr.append("0" + QString(hrBa) + "000001");
}
else
{
adsNum[0] = (int)hrBa.at(0);
adsNum[1] = (int)hrBa.at(1);
startStr.append(QString(hrBa) + "000001");
}
//qDebug()<<"num[0]:"<<num[0]<<" num[1]:"<<num[1];
quint8 sendBuf[30];
memset(sendBuf,0,30);
sendBuf[0] = (quint8)0x40; //@ 64
sendBuf[1] = (quint8)0x30; //0 48
sendBuf[2] = (quint8)0x30; //0 48
sendBuf[3] = (quint8)0x46; //F 70
sendBuf[4] = (quint8)0x41; //A 65
sendBuf[5] = (quint8)0x30; //0 48
sendBuf[6] = (quint8)0x30; //0 48
sendBuf[7] = (quint8)0x30; //0 48
sendBuf[8] = (quint8)0x30; //0 48
sendBuf[9] = (quint8)0x30; //0 48
sendBuf[10] = (quint8)0x30; //0 48
sendBuf[11] = (quint8)0x30; //0 48
sendBuf[12] = (quint8)0x30; //0 48
sendBuf[13] = (quint8)0x30; //0 48
sendBuf[14] = (quint8)0x30; //0 48
sendBuf[15] = (quint8)0x31; //1 49
sendBuf[16] = (quint8)0x30; //0 48
sendBuf[17] = (quint8)0x31; //1 49
sendBuf[18] = (quint8)0x42; //B 66
sendBuf[19] = (quint8)0x32; //2 50
sendBuf[20] = (quint8)0x30; //0 48
sendBuf[21] = (quint8)0x30; //0 48
sendBuf[22] = (quint8)adsNum[0]; //0 48
sendBuf[23] = (quint8)adsNum[1]; //1 49
sendBuf[24] = (quint8)0x30; //0 48
sendBuf[25] = (quint8)0x30; //0 48
sendBuf[26] = (quint8)0x30; //0 48
sendBuf[27] = (quint8)0x30; //0 48
sendBuf[28] = (quint8)0x30; //0 48
sendBuf[29] = (quint8)0x31; //1 49
quint8 fcsNum = 0;
for(int i=0;i<30;i++)
{
fcsNum ^= sendBuf[i];
}
QByteArray fcsBa;
fcsBa.setNum(fcsNum,16);
//qDebug()<<"fcs:"<<fcs;
QString scsStr = "";
if(fcsBa.size() == 1)
{
scsStr = "0" + QString(fcsBa);
}
else
{
scsStr = QString(fcsBa);
}
//qDebug()<<"ab:"<<ab;
startStr.append(scsStr + "*\r");
QString lastStr = startStr.toUpper();
//qDebug()<<"lastStr:"<<lastStr;
int sizeNum = lastStr.size();
QString showStr = lastStr.left(sizeNum - 1);
ui->plainTextEdit->appendPlainText("发送读命令:\n" + showStr + "\\CR");
char *readStr;
QByteArray readBa = lastStr.toLatin1();
readStr = readBa.data();
qDebug()<<"readStr:"<<readStr;
serial->write(readStr);
}
//单写HR位地址
void SerialPort::slot_writeHRBitData(int address,int bit,int numWrite)
{
//H保持区 字:B2 位:32
//@ 00 FA 0 00 00 00 00 0102 32 00 1900(address) 00 01 01(data) **(FCS) *\CR
//QString testStr = "@00FA000000000010232001900000101";
//address
QString startStr = "@00FA00000000001023200";
int adsNum[2];
QByteArray hrBa;
hrBa.setNum(address,16);
if(address < 16)
{
adsNum[0] = 0;
adsNum[1] = address;
startStr.append("0" + QString(hrBa));
}
else
{
adsNum[0] = (int)hrBa.at(0);
adsNum[1] = (int)hrBa.at(1);
startStr.append(QString(hrBa));
}
//qDebug()<<"num[0]:"<<num[0]<<" num[1]:"<<num[1];
//bit
int bitNum[2];
QByteArray bitBa;
bitBa.setNum(bit,16);
bitNum[0] = 0;
bitNum[1] = bit;
startStr.append("0" + QString(bitBa) + "0001");
//numWrite
QString numStr = QString::number(numWrite);
int numNum[2];
numNum[0] = 0;
numNum[1] = numWrite;
startStr.append("0" + numStr);
quint8 sendBuf[32];
memset(sendBuf,0,32);
sendBuf[0] = (quint8)0x40; //@ 64
sendBuf[1] = (quint8)0x30; //0 48
sendBuf[2] = (quint8)0x30; //0 48
sendBuf[3] = (quint8)0x46; //F 70
sendBuf[4] = (quint8)0x41; //A 65
sendBuf[5] = (quint8)0x30; //0 48
sendBuf[6] = (quint8)0x30; //0 48
sendBuf[7] = (quint8)0x30; //0 48
sendBuf[8] = (quint8)0x30; //0 48
sendBuf[9] = (quint8)0x30; //0 48
sendBuf[10] = (quint8)0x30; //0 48
sendBuf[11] = (quint8)0x30; //0 48
sendBuf[12] = (quint8)0x30; //0 48
sendBuf[13] = (quint8)0x30; //0 48
sendBuf[14] = (quint8)0x30; //0 48
sendBuf[15] = (quint8)0x31; //1 49
sendBuf[16] = (quint8)0x30; //0 48
sendBuf[17] = (quint8)0x32; //2 50
sendBuf[18] = (quint8)0x33; //3 51
sendBuf[19] = (quint8)0x32; //2 50
sendBuf[20] = (quint8)0x30; //0 48
sendBuf[21] = (quint8)0x30; //0 48
sendBuf[22] = (quint8)adsNum[0]; //1 49
sendBuf[23] = (quint8)adsNum[1]; //9 57
sendBuf[24] = (quint8)bitNum[0]; //0 48
sendBuf[25] = (quint8)bitNum[1]; //0 48
sendBuf[26] = (quint8)0x30; //0 48
sendBuf[27] = (quint8)0x30; //0 48
sendBuf[28] = (quint8)0x30; //0 48
sendBuf[29] = (quint8)0x31; //1 49
sendBuf[30] = (quint8)numNum[0]; //0 48
sendBuf[31] = (quint8)numNum[1]; //1 49
quint8 fcsNum = 0;
for(int i=0;i<32;i++)
{
fcsNum ^= sendBuf[i];
}
QByteArray fcsBa;
fcsBa.setNum(fcsNum,16);
//qDebug()<<"fcsBa:"<<fcsBa;
QString scsStr = "";
if(fcsBa.size() == 1)
{
scsStr = "0" + QString(fcsBa);
}
else
{
scsStr = QString(fcsBa);
}
//qDebug()<<"ab:"<<ab;
startStr.append(scsStr + "*\r");
QString lastStr = startStr.toUpper();
//qDebug()<<"lastStr:"<<lastStr;
int sizeNum = lastStr.size();
QString showStr = lastStr.left(sizeNum - 1);
ui->plainTextEdit->appendPlainText("发送写命令:\n" + showStr + "\\CR");
char *writeStr;
QByteArray writeBa = lastStr.toLatin1();
writeStr = writeBa.data();
qDebug()<<"writeStr:"<<writeStr;
serial->write(writeStr);
}
//单读HR位地址
void SerialPort::slot_readHRBitData(int address,int bit)
{
//H保持区 字:B2 位:32
//@ 00 FA 0 00 00 00 00 0101 32 00 1900(address) 00 01 **(FCS) *\CR
//QString testStr = "@00FA0000000000102320019000001";
//address
QString startStr = "@00FA00000000001013200";
int adsNum[2];
QByteArray hrBa;
hrBa.setNum(address,16);
if(address < 16)
{
adsNum[0] = 0;
adsNum[1] = address;
startStr.append("0" + QString(hrBa));
}
else
{
adsNum[0] = (int)hrBa.at(0);
adsNum[1] = (int)hrBa.at(1);
startStr.append(QString(hrBa));
}
//qDebug()<<"num[0]:"<<num[0]<<" num[1]:"<<num[1];
//bit
int bitNum[2];
QByteArray bitBa;
bitBa.setNum(bit,16);
bitNum[0] = 0;
bitNum[1] = bit;
startStr.append("0" + QString(bitBa) + "0001");
quint8 sendBuf[30];
memset(sendBuf,0,32);
sendBuf[0] = (quint8)0x40; //@ 64
sendBuf[1] = (quint8)0x30; //0 48
sendBuf[2] = (quint8)0x30; //0 48
sendBuf[3] = (quint8)0x46; //F 70
sendBuf[4] = (quint8)0x41; //A 65
sendBuf[5] = (quint8)0x30; //0 48
sendBuf[6] = (quint8)0x30; //0 48
sendBuf[7] = (quint8)0x30; //0 48
sendBuf[8] = (quint8)0x30; //0 48
sendBuf[9] = (quint8)0x30; //0 48
sendBuf[10] = (quint8)0x30; //0 48
sendBuf[11] = (quint8)0x30; //0 48
sendBuf[12] = (quint8)0x30; //0 48
sendBuf[13] = (quint8)0x30; //0 48
sendBuf[14] = (quint8)0x30; //0 48
sendBuf[15] = (quint8)0x31; //1 49
sendBuf[16] = (quint8)0x30; //0 48
sendBuf[17] = (quint8)0x31; //1 49
sendBuf[18] = (quint8)0x33; //3 51
sendBuf[19] = (quint8)0x32; //2 50
sendBuf[20] = (quint8)0x30; //0 48
sendBuf[21] = (quint8)0x30; //0 48
sendBuf[22] = (quint8)adsNum[0]; //1 49
sendBuf[23] = (quint8)adsNum[1]; //9 57
sendBuf[24] = (quint8)bitNum[0]; //0 48
sendBuf[25] = (quint8)bitNum[1]; //0 48
sendBuf[26] = (quint8)0x30; //0 48
sendBuf[27] = (quint8)0x30; //0 48
sendBuf[28] = (quint8)0x30; //0 48
sendBuf[29] = (quint8)0x31; //1 49
quint8 fcsNum = 0;
for(int i=0;i<30;i++)
{
fcsNum ^= sendBuf[i];
}
QByteArray fcsBa;
fcsBa.setNum(fcsNum,16);
//qDebug()<<"fcsBa:"<<fcsBa;
QString scsStr = "";
if(fcsBa.size() == 1)
{
scsStr = "0" + QString(fcsBa);
}
else
{
scsStr = QString(fcsBa);
}
//qDebug()<<"ab:"<<ab;
startStr.append(scsStr + "*\r");
QString lastStr = startStr.toUpper();
//qDebug()<<"lastStr:"<<lastStr;
int sizeNum = lastStr.size();
QString showStr = lastStr.left(sizeNum - 1);
ui->plainTextEdit->appendPlainText("发送读命令:\n" + showStr + "\\CR");
char *readStr;
QByteArray readBa = lastStr.toLatin1();
readStr = readBa.data();
qDebug()<<"readStr:"<<readStr;
serial->write(readStr);
}
void SerialPort::on_pb_refresh_clicked()
{
ui->cb_port->clear();
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->cb_port->addItem(info.portName());
serial.close();
}
}
}
void SerialPort::on_pb_operate_clicked()
{
if(ui->cb_port->currentText().isEmpty())
{
QMessageBox::information(this, tr("提示"),"请先刷新并进行串口选择!");
return;
}
if(ui->pb_operate->text() == QString("OPEN"))
{
QString portName = ui->cb_port->currentText();
QString baudRate = ui->cb_baud->currentText();
qDebug()<<"portName:"<<portName<<" baudRate:"<<baudRate;
QSerialPortInfo info(portName);
if(info.isBusy())
{
qDebug()<<"The serial port is occupied"<<portName;
return;
}
serial->setPortName(portName);
serial->setBaudRate(baudRate.toInt());
serial->setStopBits(QSerialPort::TwoStop);
serial->setDataBits(QSerialPort::Data7);
serial->setParity(QSerialPort::EvenParity);
serial->setFlowControl(QSerialPort::NoFlowControl);
bool flag = serial->open(QIODevice::ReadWrite);
if(!flag)
{
qDebug()<<QString("Failed to open serial port:")<<portName<<serial->errorString();
serial->clearError();
ui->pb_send->setEnabled(false);
}
else
{
qDebug()<<QString("The serial port is open:")<<portName;
ui->pb_operate->setText("CLOSE");
ui->pb_send->setEnabled(true);
}
}
else
{
ui->pb_operate->setText("OPEN");
serial->close();
ui->pb_send->setEnabled(false);
}
}
void SerialPort::on_pb_send_clicked()
{
//1.界面上显示的是ASCII字符
//2.计算校验码的步骤
//3.先进行输入地址位的转换
//4.将界面上字符转化为十进制后进行按位异或运算
//5.按位运算后的结果转换为16进制即为校验码
int address = ui->le_address->text().toInt();
int bit = ui->le_bit->text().toInt();
int numWrite = ui->le_num->text().toInt();
//单读
if(ui->rb_read->isChecked())
{
if(ui->le_bit->text().isEmpty())
{
slot_readHRWordData(address);
}
else
{
slot_readHRBitData(address,bit);
}
}
//单写
if(ui->rb_write->isChecked())
{
if(ui->le_bit->text().isEmpty())
{
slot_writeHRWordData(address,numWrite);
}
else
{
slot_writeHRBitData(address,bit,numWrite);
}
}
}
void SerialPort::on_rb_read_clicked()
{
ui->le_num->setEnabled(false);
}
void SerialPort::on_rb_write_clicked()
{
ui->le_num->setEnabled(true);
}
4.serialport.ui
四、下载链接
我的示例百度网盘链接:https://pan.baidu.com/s/1eGnt6I7UVeN5p3n4bvLVTA
提取码:xxcj
总结
本文实现的与欧姆龙PLC进行的通信也是比较简单的,使用串口进行命令的发送,前提是对HOSTLINK协议有相应的了解,然后去实现该协议命令的组装,其中需要注意的一个点是FCS(校验码)的获取。本文还存在的局限是只进行了HR区域的读写,并且只能进行单独某地址或某位的读写,所以想要实现更多区域的读写就需要进行改进了,这里提供这样一个示例,希望可以帮助到大家。
hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。
参考博客:
欧姆龙plc交互协议hostlink
基于HostLink协议的Fins命令读写