Realize Omron PLC serial port sending HOSTLINK (FINS) mode under Qt


foreword

This article describes the HOSTLINK (FINS) mode sent by the simulated serial port debugging tool under Qt. It mainly reads and writes words and bits in the HR holding area, and shows the calculation method of the check code (FCS) in the HOSTLINK protocol. See below for details. The code, I hope it can help everyone, if there are any mistakes, everyone is welcome to criticize and correct.

Project effect
Please add a picture description


提示:以下是本篇文章正文内容,下面案例可供参考

1. Description of HOSTLINK protocol

The detailed format of the HOSTLINK (FINS) command is shown in the figure below.
Please add a picture description
Here is an explanation of the FINS command format (see the manual for details)
(a), command code (command code)
0101: read command
0102: write command
(b), IO Memory Area Code (memory area address)
WR(Word): B1
WR(Bit): 31
HR(Word): B2
HR(Bit): 32
… …

Here is an example to illustrate the above format:
//Single write HR word address (HR1 write data 1) write: 0102 word: B2
@ 00 FA 0 00 00 00 00 0102 B2 00 01(address) 00 00 01 0001(data ) **(FCS) *\CR

//Single read HR word address (read the value on HR1 address) Read: 0101 Word: B2
@ 00 FA 0 00 00 00 00 0101 B2 00 01(address) 00 00 01 **(FCS) *\CR

//Single write HR bit address (write data 1 to HR1.01 bit) Write: 0102 bit: 32
@ 00 FA 0 00 00 00 00 0102 32 00 0101(address) 00 01 01(data) **(FCS) *\CR

//Single read HR bit address (read the value on HR1.01 bit) Read: 0101 bit: 32
@ 00 FA 0 00 00 00 00 0101 32 00 0101(address) 00 01 **(FCS) *\CR

2. Check code (FCS) calculation

FCS field in the agreement: Occupying two characters, the value is the result of the bitwise XOR operation of the ASCII codes of all characters from @ to the end of the text. Steps to calculate the check code:
1. Convert the input address bits first.
2. ASCII characters are displayed on the interface. Convert the characters on the interface into decimals and perform bitwise XOR operation.
3. The result of the bitwise operation is converted into Hexadecimal is the check code

3. Example complete code

1. The serial port related functions are used in the example, so the following code needs to be added to the 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
Please add a picture description

4. Download link

My example Baidu network disk link: https://pan.baidu.com/s/1eGnt6I7UVeN5p3n4bvLVTA
extraction code: xxcj


Summarize

The communication with Omron PLC realized in this article is also relatively simple. The serial port is used to send commands. The premise is to have a corresponding understanding of the HOSTLINK protocol, and then to realize the assembly of the protocol commands. One point that needs attention is FCS (school check code) acquisition. The limitation of this article is that it only reads and writes the HR area, and only reads and writes a single address or a certain bit, so it needs to be improved if it wants to read and write more areas. Here is such an example , I hope it can help everyone.


hello:
Learn together and make progress together. If you still have related questions, you can leave a message in the comment area for discussion.

Reference blog:
Omron plc interactive protocol hostlink
reads and writes Fins commands based on HostLink protocol

Guess you like

Origin blog.csdn.net/XCJandLL/article/details/128786473