QT modbus类简介及串口modbus例程源码分析

1.Qt中几个常用的串口modbus类

QModbusRtuSerialSlave         //modbus串口通信方式下的服务器类

QModbusRtuSerialMaster      //串口通信方式下的客户端类

QModbusServer                     // QModbusServer类接收和处理modbus的请求。

QModbusDataUnit                //存储接收和发送数据的类,数据类型为1bit和16bit

QModbusReply                     //客户端访问服务器后得到的回复(如客户端读服务器数据时包含数据信息)

 2.modbusMaster发送数据代码流程

QT modbus类简介及串口modbus例程源码分析_第1张图片

3.部分代码及注释

void modbusMaster::on_connectButton_clicked()//连接按钮点击槽方法
{
    if (!modbusDevice)
        return;
    statusBar()->clearMessage();
    QString comPortName = ui->lineEdit->text();
    if (modbusDevice->state() != QModbusDevice::ConnectedState) {//如果处在非连接状态,进行连接
        //进行串口连接
        modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
            comPortName);//获取串口端口,下面设置各种参数
        modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
            QSerialPort::EvenParity);//偶较验
        modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
            QSerialPort::Baud19200);//波特率为19200
        modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
            QSerialPort::Data8);//数据位为8位
        modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
            QSerialPort::OneStop);//停止位为1位
        modbusDevice->setTimeout(1000);//连接超时1S
        modbusDevice->setNumberOfRetries(3);//连接失败重试三次连接
        if (!modbusDevice->connectDevice()) {
            statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
        }
    }else{//处在连接状态进行断开连接的操作
        modbusDevice->disconnectDevice();
    }
}


void modbusMaster::on_sendButton_clicked()
{
    if (!modbusDevice)//如果设备没有被创建就返回
        return;
    QString strDis;
    QString str1 = ui->textEdit->toPlainText();
    qDebug()<     QByteArray str2 = QByteArray::fromHex (str1.toLatin1().data());//按十六进制编码接入文本
    //qDebug()<     QString str3 = str2.toHex().data();//以十六进制显示
    statusBar()->clearMessage();//清除状态栏显示的信息
    QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,0,10);//发送的数据信息(数据类型 ,起始地址,个数)
//    QModbusDataUnit::RegisterType table = writeUnit.registerType();//得到寄存器类型传给table
    for (uint i = 0; i < writeUnit.valueCount(); i++) {
        int j = 2*i;
        QString st = str3.mid (j,2);
        bool ok;
        int hex =st.toInt(&ok,16);//将textedit中读取到的数据转换为16进制发送
        qDebug()<         writeUnit.setValue(i,hex);//设置发送数据
    }
    if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, 1)) {// 1是server address   sendWriteRequest是向服务器写数据
        if (!reply->isFinished()) {   //reply Returns true when the reply has finished or was aborted.
            connect(reply, &QModbusReply::finished, this, [this, reply]() {
                if (reply->error() == QModbusDevice::ProtocolError) {
                    statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)")
                        .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
                        5000);
                } else if (reply->error() != QModbusDevice::NoError) {
                    statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
                        arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
                }
                reply->deleteLater();
            });
        } else {
            // broadcast replies return immediately
            reply->deleteLater();
        }
    } else {
        statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
    }
}

void modbusMaster::on_readButton_clicked()//从服务器读数据的读按钮槽方法
{
    if (!modbusDevice)
        return;
    statusBar()->clearMessage();
    QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters,0,10);
    if (auto *reply = modbusDevice->sendReadRequest(readUnit, 1)) {
        if (!reply->isFinished())
            connect(reply, &QModbusReply::finished, this, &modbusMaster::readReady);
        else
            delete reply; // broadcast replies return immediately
    } else {
        statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000);
    }
}


void modbusMaster::readReady()//在这里读的数据
{
    auto reply = qobject_cast(sender());//QModbusReply这个类存储了来自client的数据,sender()返回发送信号的对象的指针
    if (!reply)
        return;
//数据从QModbusReply这个类的resuil方法中获取,也就是本程序中的reply->result()
    if (reply->error() == QModbusDevice::NoError) {
        const QModbusDataUnit unit = reply->result();
        for (uint i = 0; i < unit.valueCount(); i++) {
            const QString entry = tr("Address: %1, Value: %2").arg(unit.startAddress())
                                     .arg(QString::number(unit.value(i),
                                          unit.registerType() <= QModbusDataUnit::Coils ? 10 : 16));
            ui->textEdit_2->append(entry);
        }
    } else if (reply->error() == QModbusDevice::ProtocolError) {
        statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
                                    arg(reply->errorString()).
                                    arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
    } else {
        statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
                                    arg(reply->errorString()).
                                    arg(reply->error(), -1, 16), 5000);
    }
    reply->deleteLater();
}

程序效果如图所示

QT modbus类简介及串口modbus例程源码分析_第2张图片


4.modbusSlave接收数据代码流程

QT modbus类简介及串口modbus例程源码分析_第3张图片

5.slave数据部分代码及注释

modbusSlave::modbusSlave(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::modbusSlave)
{
    ui->setupUi(this);
    modbusDevice = new QModbusRtuSerialSlave(this);
    QModbusDataUnitMap reg;//设置可接收的寄存器数据类型
    reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 });//
    reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 });
    reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 });
    reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 });

    modbusDevice->setMap(reg);//
    connect(modbusDevice, &QModbusServer::stateChanged,
            this, &modbusSlave::onStateChanged);//连接状态发生改变时改变connect按钮上的显示文字(connect or discennect)
    connect(modbusDevice, &QModbusServer::dataWritten,
            this, &modbusSlave::updateWidgets);//modbus客户端向服务器写入数据时dataWritten信号被触发
    connect(modbusDevice, &QModbusServer::errorOccurred,
            this, &modbusSlave::handleDeviceError);
}

void modbusSlave::updateWidgets(QModbusDataUnit::RegisterType table, int address, int size)//dataWriten信号被处发后,得到数据做出显示
{
    for (int i = 0; i < size; ++i) {
        quint16 value;
        switch (table) {
        case QModbusDataUnit::Coils:
            modbusDevice->data(QModbusDataUnit::Coils, address + i, &value);
            qDebug()<             break;
        case QModbusDataUnit::HoldingRegisters:
            modbusDevice->data(QModbusDataUnit::HoldingRegisters, address + i, &value);//得到数据后做出显示
            qDebug()<             break;
        default:
            break;
        }
        QString s = QString::number(value, 16);
        qDebug("%d",value);
        ui->textEdit->append(s);
    }
}

程序运行效果

QT modbus类简介及串口modbus例程源码分析_第4张图片

总体效果图

QT modbus类简介及串口modbus例程源码分析_第5张图片

完整程序地址:http://download.csdn.net/detail/maowendi/9598219


你可能感兴趣的:(Qt)