QT QModbusTcpClient使用ModbusTcp协议与硬件通信实战例子

这篇具有很好参考价值的文章主要介绍了QT QModbusTcpClient使用ModbusTcp协议与硬件通信实战例子。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  1.需求

    给了一个显示屏和显示屏的通信文档,用ModbusTcp协议与其通信,读取或者写入显示屏相应的内容,以满足项目需要
文档部分截图如下
qt plc modbus tcp,Qt开发,ModbusTcp,qt,开发语言
屏幕如下图所示:
qt plc modbus tcp,Qt开发,ModbusTcp,qt,开发语言
我需要写入改写其中的物料名称,待领料数量等,就是上位机与硬件通信

2.方案

1.常规方案,使用QTcpSocket

对于熟悉modbusTcp协议的,可以根据协议和通信文档完成信息的封装在发送给硬件即可

2.使用现有造好的轮子,QModbusTcpClient

需要熟悉QModbusTcpClient的接口,参数等,我们还没有用过
本来想请教项目组其他人的,他们让我先看下modbusTcp协议,熟悉一下,我看了好久,没有实际案例,有点抽象,他们也忙,没啥空,没时间了,还是用现有的轮子吧

然后我就决定采用QModbusTcpClient的方案进行吧

3.最后我决定采用QModbusTcpClient

采用QModbusTcpClient和QTcpSocket本质差不多,都是通过tcp进行通信,QTcpSocket需要自己封装相应的modbusTcp协议内容,发送给硬件服务器
QModbusTcpClient封装好了modbusTcp协议,你只需要理解好,然后填入相应的参数和调用相应的接口就行了,不需要理解modbusTcp协议,对于第一次解除的人来说,只是项目需要,不需要深入理解的,最合适不过了

4、实例代码解析

QModbusTcpClient像QTcpSocket一样,首先得连接到相应的服务器,通过setConnectionParameter函数设置要连接的ip和端口号,设置超时值,和服务器没有回应时的重发次数,最后连接上去即可,如下

 modbusClient = new QModbusTcpClient(this);
    //连接状态发生改变时处理函数(connect or discennect)
    modbusClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ui->ip->text());
    modbusClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, ui->port->text().toInt());
    modbusClient->setTimeout(500);
    modbusClient->setNumberOfRetries(3);//服务器没有回应的重发次数
    modbusClient->connectDevice();//


判断QModbusTcpClient有没有连接上服务器,使用它的信号判断即可

connect(modbusClient, &QModbusClient::stateChanged, this, &Widget::onStateChanged);
void Widget::onStateChanged(QModbusDevice::State newState)
{
    if (newState == QModbusDevice::ConnectedState) {
        qDebug()<<"QModbusDevice连接成功";
        ui->send->setDisabled(false);
       // 连接成功
   } else if (newState == QModbusDevice::UnconnectedState) {
       // 连接断开
        qDebug()<<"QModbusDevice连接断开";
        ui->send->setDisabled(true);
   }
}

接下来就是如何写入数据了,数据的封装采用QModbusDataUnit进行,然后将这个对象丢给QModbusClient的接口发送给服务器就行了
我这里使用QModbusDataUnit的默认构造函数初始化一个对象出来,第一个参数是寄存器类型,第二个参数是寄存器地址,第三个参数是寄存器数量
QModbusDataUnit(QModbusDataUnit::RegisterType type, int address, quint16 size)

例如我的例子中,寄存器的地址为10029,寄存器数量为14

qt plc modbus tcp,Qt开发,ModbusTcp,qt,开发语言

QModbusDataUnit writeNameUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->name_reg->text().toInt(), 14);

qt plc modbus tcp,Qt开发,ModbusTcp,qt,开发语言

......

qt plc modbus tcp,Qt开发,ModbusTcp,qt,开发语言寄存器类型有如下选择,我这里只用到可以进行读写的保存寄存器

Constant

Value

Description

QModbusDataUnit::Invalid

0

由默认构造函数设置,不要使用

QModbusDataUnit::DiscreteInputs

1

离散输入:这种类型的数据可以由I/O系统提供

QModbusDataUnit::Coils

2

线圈:这种类型的数据可以通过应用程序进行更改

QModbusDataUnit::InputRegisters

3

输入寄存器:这种类型的数据可以由I/O系统提供。

QModbusDataUnit::HoldingRegisters

4

保持寄存器:这种类型的数据可以通过应用程序进行更改

接下来就是怎么为QModbusDataUnit设值的问题了,用这个函数设值就行,第一个参数为寄存器的索引,第二个参数为对应的寄存器的值
 

void QModbusDataUnit::setValue(int index, quint16 value)


值得注意的是,从它的值定义就可以看到,quint16,就是个十进制整形,不能设置为16进制的
如果是16进制的,得先把16进制转化成十进制的才行,他会在内部自己封装成16进制的,这个我也有点奇怪的点
如果是设置数字的,就简单了,根据文档中对应的字节数和寄存器数量即可,一个寄存器一般存两个字节

QModbusDataUnit unit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->name_reg->text().toInt(), 2);
uint count = unit.valueCount();
if(count==1) {
    unit.setValue(0, static_cast<quint16>(data.toInt(&ok,10)));
}
else {
    int num0 = data.toInt()/65536;
    int num1 = data.toInt()%65536;
    unit.setValue(0, static_cast<quint16>(num0));
    unit.setValue(1, static_cast<quint16>(num1));
}

我看文档里面写整形的数据时,整形数据最多占用四个字节,即两个寄存器,所以要根据实际情况来

如果要写入汉字的话,一般要求的是 字库:GBK的编码,我们将Unicode转GBK,然后在转16进制即可,如果数据不够长,可以将没有数据的寄存器填充完,根据硬件文档来就行了,一般填充‘0’或者‘F’,然后在根据每个寄存器可容纳的字节数,将完整的16进制数据分割,用于填充寄存器,一般每个寄存器可容纳的字节数=4个字节,所以每四个字符用空格分割下即可

如果要写入不包含汉字的字符串,一般要求的是 字库:ASCII编码,这个我们直接将字符串中的每个字符转换为16进制的即可。

    uint count = unit.valueCount();    
    if(type == DataType::GBK) {
         QByteArray byteGB2312 = utf8ToGB2312(data);
         for(uint i=byteGB2312.length(); i<count*4; i++) {
             byteGB2312.append("0");
         }
         qDebug()<<"byteGB2312:"<<byteGB2312;
         m_data = byteGB2312;
         int size = byteGB2312.size()/4-1;
         //用空格两个每组分隔开
         for(int i=1; i<=size; i++) {
             byteGB2312.insert(i*4+i-1, " ");
         }
         QByteArrayList list = byteGB2312.split(' ');
         bool ok;
         qDebug()<<list;
         QVector<quint16> values;

         for(int i=0; i<list.size(); i++) {
             quint16 num = static_cast<quint16>(list.at(i).toInt(&ok, 16));
             unit.setValue(i, num);
         }
    }
    else if(type==DataType::ASCII) {
        QByteArray ASCII = stringToASCII(data);
       
        for(uint i=ASCII.length(); i<count*4; i++) {
            ASCII.append("F");
        }

        qDebug()<<"ASCII:"<<ASCII;
        int size = ASCII.size()/4-1;
        //用空格两个每组分隔开
        for(int i=1; i<=size; i++) {
            ASCII.insert(i*4+i-1, " ");
        }
        QByteArrayList list = ASCII.split(' ');
        bool ok;
        qDebug()<<list;
        for(int i=0; i<list.size(); i++) {
            quint16 num = static_cast<quint16>(list.at(i).toInt(&ok, 16));
            unit.setValue(i, num);
        }
    }

编码转换如下

QByteArray Widget::utf8ToGB2312(QString utf8Data)
{

    //原始UTF8数据
    QString strOrgData(utf8Data);
    QTextCodec *utf8 = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(utf8);

    //1.UTF8 ---> GBK
    //UTF8转unicode
    QString strUnicode= utf8->toUnicode(strOrgData.toLocal8Bit().data());

    //Unicode转GBK
    QTextCodec *gbk = QTextCodec::codecForName("gbk");
    //转化为16进制
    QByteArray bytegbkHex = gbk->fromUnicode(strUnicode).toHex();
    return bytegbkHex;
}

QByteArray Widget::stringToASCII(QString data)
{
    //QByteArray byte = data.toUtf8();
    QByteArray byte = data.toUtf8();
    QByteArray byteASCII;
    for(char c: byte) {
        byteASCII += QString::number(int(c), 16);
    }
    return byteASCII;
}

最后发送给服务端即可,使用的函数为

QModbusReply *QModbusClient::sendWriteRequest(const QModbusDataUnit &write, int serverAddress)

第一个参数为已封装的数据unit,第二个参数为设备地址,根据文档或者询问厂家即可

void Widget::sendWriteRequest(QModbusDataUnit &unit, int address)
{
    qDebug() << "写数据内容为:" << unit.values();
    auto *reply = modbusClient->sendWriteRequest(unit, address);
    if (reply)
    {
        if (!reply->isFinished())
        {
            //完毕之后 自动触发槽函数
            connect(reply, &QModbusReply::finished, this, [this, reply]{
                if (reply->error() == QModbusDevice::ProtocolError)
                {
                    qDebug()<<QString("Write Protocaol response error: %1").arg(reply->errorString());
                }
                else if (reply->error() != QModbusDevice::NoError)
                {
                    qDebug()<<QString("Write response error: %1").arg(reply->errorString());
                }
                else
                {
                    qDebug() << "写响应的数据: " << reply->result().values();
                }
                reply->deleteLater();

            });
        }
        else
        {
            //广播消息  不需要返回响应
            reply->deleteLater();
        }
    }
    else
    {
        qDebug()<<QString(("Write Error: ") + modbusClient->errorString());
    }


}

我写的例子最终效果图如下:

qt plc modbus tcp,Qt开发,ModbusTcp,qt,开发语言

5、QModbusTcpClient的缺点

1. 只能看到封装发送的QVector,不能看到实时发送的报文,接收响应的报文也是如此

2. 内部方法中也没有相应的函数,可以查看发送的或者接收的真正报文

----写入物料名称----
byteGB2312: "c4e3bac33132333435c4e3bac3000000000000000000000000000000"
("c4e3", "bac3", "3132", "3334", "35c4", "e3ba", "c300", "0000", "0000", "0000", "0000", "0000", "0000", "0000")
写数据内容为: QVector(50403, 47811, 12594, 13108, 13764, 58298, 49920, 0, 0, 0, 0, 0, 0, 0)
----写入物料信息----
ASCII: "4231323334353600FFFFFFFF"
("4231", "3233", "3435", "3600", "FFFF", "FFFF")
写数据内容为: QVector(16945, 12851, 13365, 13824, 65535, 65535)
----写入物料编码----
ASCII: "3132333435363700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
("3132", "3334", "3536", "3700", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF")
写数据内容为: QVector(12594, 13108, 13622, 14080, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535)
----写入存量数----
写数据内容为: QVector(30)
----写入待领料数量----
写数据内容为: QVector(0, 2)
----------------------写入完成----------------
写响应的数据:  QVector(50403, 47811, 12594, 13108, 13764, 58298, 49920, 0, 0, 0, 0, 0, 0, 0)
写响应的数据:  QVector(16945, 12851, 13365, 13824, 65535, 65535)
写响应的数据:  QVector(12594, 13108, 13622, 14080, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535)
写响应的数据:  QVector(30)
写响应的数据:  QVector(0, 2)

这个是源码编写时忘记写了嘛?那我就找别的途径了吧

解决方案:自己写一个服务端,然后我们连接上,看接收的消息即可

qt plc modbus tcp,Qt开发,ModbusTcp,qt,开发语言

核心代码如下:文章来源地址https://www.toymoban.com/news/detail-822897.html

void Widget::writeDate()
{
    if(modbusClient->state() == QModbusDevice::UnconnectedState) {
        qDebug()<<"Device is not connected";
        return;
    }

    QString code = ui->code->text();
    QString name = ui->name->text();
    QString stock = ui->stock->text();
    QString amount = ui->getAmount->text();
    QString matInfo = ui->matInfo->text();
    QString minStock = ui->minStock->text();
    if(!name.isEmpty()) {
        qDebug()<<"----写入物料名称----";
        QModbusDataUnit writeNameUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->name_reg->text().toInt(), 14);
        createModbusDataUnit(writeNameUnit, name, DataType::GBK);
        sendWriteRequest(writeNameUnit, 1);
    }
    QThread::msleep(100);
    if(!matInfo.isEmpty()) {
        qDebug()<<"----写入物料信息----";
        QModbusDataUnit writeMatInfoUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->matInfo_reg->text().toInt(), 6);
        createModbusDataUnit(writeMatInfoUnit, matInfo, DataType::ASCII);
        sendWriteRequest(writeMatInfoUnit, 1);
        QThread::msleep(100);
    }
    if(!code.isEmpty()) {
        qDebug()<<"----写入物料编码----";
        QModbusDataUnit writeCodeUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->code_reg->text().toInt(), 14);
        createModbusDataUnit(writeCodeUnit, code, DataType::ASCII);
        sendWriteRequest(writeCodeUnit, 1);
        QThread::msleep(100);
    }
    if(!stock.isEmpty()) {
        qDebug()<<"----写入存量数----";
        QModbusDataUnit writeStockUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->stock_reg->text().toInt(), 1);
        createModbusDataUnit(writeStockUnit, stock, DataType::INT);
        sendWriteRequest(writeStockUnit, 1);
        QThread::msleep(100);
    }
    if(!amount.isEmpty()) {
        qDebug()<<"----写入待领料数量----";
        QModbusDataUnit writeAmountUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->getAmount_reg->text().toInt(), 2);
        createModbusDataUnit(writeAmountUnit, amount, DataType::INT);
        sendWriteRequest(writeAmountUnit, 1);
        QThread::msleep(100);
    }
    if(!minStock.isEmpty()) {
        qDebug()<<"----写入最低存量----";
        QModbusDataUnit writeminStockUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, ui->minStock_reg->text().toInt(), 2);
        createModbusDataUnit(writeminStockUnit, minStock, DataType::INT);
        sendWriteRequest(writeminStockUnit, 1);
        QThread::msleep(100);
    }
    qDebug()<<"----------------------写入完成----------------";
}

void Widget::onStateChanged(QModbusDevice::State newState)
{
    if (newState == QModbusDevice::ConnectedState) {
        qDebug()<<"QModbusDevice连接成功";
        ui->send->setDisabled(false);
       // 连接成功
   } else if (newState == QModbusDevice::UnconnectedState) {
       // 连接断开
        qDebug()<<"QModbusDevice连接断开";
        ui->send->setDisabled(true);
   }

}


void Widget::createModbusDataUnit(QModbusDataUnit &unit, QString &data,  DataType type)
{
    switch (type) {
        case DataType::INT: {
            bool ok;
            uint count = unit.valueCount();
            if(count==1) {
                unit.setValue(0, static_cast<quint16>(data.toInt(&ok,10)));
            }
            else {
                int num0 = data.toInt()/65536;
                int num1 = data.toInt()%65536;
                unit.setValue(0, static_cast<quint16>(num0));
                unit.setValue(1, static_cast<quint16>(num1));
            }
            break;
        }
        case DataType::GBK:
        case DataType::ASCII:
        {
            packDataUnit(unit, data, type);
            break;
        }
    }


}

void Widget::sendWriteRequest(QModbusDataUnit &unit, int address)
{
    qDebug() << "写数据内容为:" << unit.values();
    auto *reply = modbusClient->sendWriteRequest(unit, address);
    if (reply)
    {
        if (!reply->isFinished())
        {
            //完毕之后 自动触发槽函数
            connect(reply, &QModbusReply::finished, this, [this, reply]{
                if (reply->error() == QModbusDevice::ProtocolError)
                {
                    qDebug()<<QString("Write Protocaol response error: %1").arg(reply->errorString());
                }
                else if (reply->error() != QModbusDevice::NoError)
                {
                    qDebug()<<QString("Write response error: %1").arg(reply->errorString());
                }
                else
                {
                    qDebug() << "写响应的数据: " << reply->result().values();
                }
                reply->deleteLater();

            });
        }
        else
        {
            //广播消息  不需要返回响应
            reply->deleteLater();
        }
    }
    else
    {
        qDebug()<<QString(("Write Error: ") + modbusClient->errorString());
    }


}

void Widget::packDataUnit(QModbusDataUnit &unit, QString &data, DataType type)
{
    uint count = unit.valueCount();
    if(type == DataType::GBK) {
         QByteArray byteGB2312 = utf8ToGB2312(data);
         for(uint i=byteGB2312.length(); i<count*4; i++) {
             byteGB2312.append("0");
         }
         qDebug()<<"byteGB2312:"<<byteGB2312;
         m_data = byteGB2312;
         int size = byteGB2312.size()/4-1;
         //用空格两个每组分隔开
         for(int i=1; i<=size; i++) {
             byteGB2312.insert(i*4+i-1, " ");
         }
         QByteArrayList list = byteGB2312.split(' ');
         bool ok;
         qDebug()<<list;
         QVector<quint16> values;

         for(int i=0; i<list.size(); i++) {
             quint16 num = static_cast<quint16>(list.at(i).toInt(&ok, 16));
             unit.setValue(i, num);
         }
    }
    else if(type==DataType::ASCII) {
        QByteArray ASCII = stringToASCII(data);
        while(ASCII.length()%4!=0) {
            ASCII.append("0");
        }
        for(uint i=ASCII.length(); i<count*4; i++) {
            ASCII.append("F");
        }

        qDebug()<<"ASCII:"<<ASCII;
        int size = ASCII.size()/4-1;
        //用空格两个每组分隔开
        for(int i=1; i<=size; i++) {
            ASCII.insert(i*4+i-1, " ");
        }
        QByteArrayList list = ASCII.split(' ');
        bool ok;
        qDebug()<<list;
        for(int i=0; i<list.size(); i++) {
            quint16 num = static_cast<quint16>(list.at(i).toInt(&ok, 16));
            unit.setValue(i, num);
        }
    }
}

QByteArray Widget::utf8ToGB2312(QString utf8Data)
{

    //原始UTF8数据
    QString strOrgData(utf8Data);
    QTextCodec *utf8 = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(utf8);

    //1.UTF8 ---> GBK
    //UTF8转unicode
    QString strUnicode= utf8->toUnicode(strOrgData.toLocal8Bit().data());

    //Unicode转GBK
    QTextCodec *gbk = QTextCodec::codecForName("gbk");
    //转化为16进制
    QByteArray bytegbkHex = gbk->fromUnicode(strUnicode).toHex();
    return bytegbkHex;
}

QByteArray Widget::stringToASCII(QString data)
{
    //QByteArray byte = data.toUtf8();
    QByteArray byte = data.toUtf8();
    QByteArray byteASCII;
    for(char c: byte) {
        byteASCII += QString::number(int(c), 16);
    }
    return byteASCII;
}

到了这里,关于QT QModbusTcpClient使用ModbusTcp协议与硬件通信实战例子的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Qt网络编程】实现TCP协议通信

    传输控制协议(TCP,Transmission Control Protocol)是 一种面向连接的、可靠的、基于字节流的传输层通信协议 ,由IETF的RFC 793 定义。 TCP建立连接前,需要进行三次握手,如下图所示: TCP断开连接前,需要进行四次挥手,如下图所示: Qt中提供了QTcpSocket类和QTcpServer类分别用于创

    2024年02月16日
    浏览(48)
  • 带你玩转modbusTCP通信

    Modbus TCP是一种基于TCP/IP协议的Modbus通信协议,它是Modbus协议的一种变体,用于在以太网上进行通信。Modbus TCP协议是一种开放的通信协议,它支持多种编程语言和操作系统,并且可以在不同的硬件和软件平台上进行通信。 Modbus TCP协议使用标准的TCP/IP协议栈,通过以太网进行通

    2024年02月03日
    浏览(47)
  • 发那科通信之MODBUSTCP(二)

    小伙伴们大家好! 上篇文章介绍了发那科机器人的modbustcp通信基础,今天把机器人的实际配置以及汇川PLC与之通信的配置和程序发出来以供大家参考,小伙伴有问题可以微信俺哦(18336146667).。。。 话不多说,直接上硬菜!!! 一、首先是机器人的通信配置  modbustcp配置以

    2024年04月14日
    浏览(28)
  • ModbusTCP协议报文解析

    交互(通信)标识 :2个字节 为此次通信事务处理标识符,一般每次通信之后将被要求加1以区别不同的通信数据报文。 协议标识 :2个字节 表示该条指令遵循ModbusTCP协议,一般都为00 00 报文长度 :2个字节 表示后面数据的长度,有几个字节,高字节在前 (前六位Modbus/TCP协议

    2024年02月02日
    浏览(37)
  • C#与西门子PLC1500的ModbusTcp服务器通信4--搭建ModbusTcp客户端

    客户端可以是一个程序或一个设备,这里我以C#WINFORM程序来实现客户机与PLC的Modbustcp服务器通信,开发环境是VS2019,.NET Framework版本是4.7.2  创建类库   编写C#各种类的转换库,该库由我提供,不用操心,文章最后提供。 项目引入这个类库  找到项目,找到引用,右键“管理

    2024年02月11日
    浏览(43)
  • C#与西门子PLC1500的ModbusTcp服务器通信3--搭建ModbusTcp服务器

     注意,这个IP地址必须与西门子虚拟网卡的IP地址及虚拟机的网卡IP地址同一网段           找到程序块main,找到右边的指令,找到通信,找到其它,拖到MB_SERVER到程序段1中    重点看mb_hold_reg和connect参数,disconnet为false表示被动连接,意思是说服务器等待客户机来连接,而

    2024年02月11日
    浏览(47)
  • 【工控通信】ModbusTCP通讯之ModbusPoll客户端工具配置

    1.安装Modbus Poll客户端工具 2.Modbus Poll客户端工具安装好以后的界面 Modbus Poll uses a multiple windows user interface. That means you can open several windows showing different data areas or data from different slave ID’s at the same time. You can write any text in the Alias cells. In any dialog box you can press the F1 key for more he

    2024年02月13日
    浏览(40)
  • Node-Red与ModbusTCP设备通信——读数据

    一、内容简介 本篇内容主要介绍Node-Red通过node-red-contrib-modbus插件与ModbusTCP设备进行通讯,这里用Modbus Slave工具来模拟从站设备,Node-Red作为主站分别从0地址开始读取10个线圈状态和10个保持寄存器,分别用Modbus-Read、Modbus-Getter、Modbus-Flex-Getter三个节点以不同的方式来实现。

    2024年01月24日
    浏览(58)
  • 博途PLC1200/1500PLC ModbusTcp通信梯形图篇(轮询)

    关于MODBUS Tcp通信的基础概念,各种通信方案的详细讲解,可以参看下面这篇博客: S7-200SMART PLC Modbus TCP通信(多服务器多从站轮询)_RXXW_Dor的博客-CSDN博客 MBUS_CLIENT作为MODBUS TCP客户端通过S7-200 SMART CPU上的以太网端口进行通信。MBUS_CLIENT可建立客户端-服务器连接、发送MODBUS功

    2024年02月06日
    浏览(123)
  • 博途PLC S7-1200/1500 ModbusTcp通信SCL代码篇(轮询)

    博途PLC MODBUS TCP的详细讲解和注意事项,可以参看下面这篇博文,这里不在赘述。这篇作为SCL代码篇主要给出SCL语言下的轮询写法和注意事项。限于本人水平和能力,文中难免出现错误和不足之处,诚恳的欢迎大家批评和指正。同时感谢大家订阅和关注。 博途PLC1200/1500PLC Mo

    2024年02月14日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包