#include "mymodbustcp.h" MyModbusTcp::MyModbusTcp() { modbusDevice = new QModbusTcpClient(); //有错误发生时,发出提示 connect(modbusDevice, &QModbusClient::errorOccurred, this, &MyModbusTcp::errorOccurred_Slot); //状态改变 if(modbusDevice == nullptr){ qDebug()<<"cannot create modbus client"; } else{ connect(modbusDevice, &QModbusClient::stateChanged, this, &MyModbusTcp::stateChanged_SLot); } } /** * @brief MyModbusTcp::timeGoBy 等待tms * @param time * @param t */ void MyModbusTcp::timeGoBy(QTime time, int t){ time.start(); //设定time为当前时间 while(time.elapsed() < t){ //等待时间流逝500ms QCoreApplication::processEvents(); //处理事件 } } //===================================数据类型转换=============================== /** * @brief MyModbusTcp::float2Word 将浮点数f转化为2个8位数据存放在word数组中 * @param f 待转换的浮点数 * @param word 转换后的word数组 */ void MyModbusTcp::float2Word(float f, unsigned int *word) { unsigned long longdata = 0; longdata = *(unsigned long*)&f; //注意,会丢失精度 word[0] = (longdata & 0xFFFF0000) >> 16; word[1] = (longdata & 0x0000FFFF); } /** * @brief MyModbusTcp::word2Float 将2个word数据转化为浮点数 * @param p 指向word数组的指针 * @param dataTransformed 转化后的浮点数 */ void MyModbusTcp:: word2Float(unsigned int *p, float dataTransformed) { dataTransformed=0; unsigned long longdata = 0; longdata = (*p<< 16) + (*(p+1) << 0); dataTransformed = *(float*)&longdata; } //==========================================modbustcp==================== /** * @brief MyModbusTcp::errorOccurred_Slot 有错误发生 */ void MyModbusTcp::errorOccurred_Slot(){ qDebug()<<"new error"<errorString(); } /** * @brief MyModbusTcp::stateChanged_SLot 状态改变 */ void MyModbusTcp::stateChanged_SLot(){ if(modbusDevice->state() == QModbusDevice::UnconnectedState){ qDebug()<<"Tcp Client未连接到server"; } else if(modbusDevice->state() == QModbusDevice::ConnectingState){ qDebug()<<"正在连接"; } else if(modbusDevice->state() == QModbusDevice::ConnectedState){ qDebug()<<"已连接"; } else if(modbusDevice->state() == QModbusDevice::ClosingState){ qDebug()<<"已关闭"; } } /** * @brief MyModbusTcp::connectModbusTcp 连接ModbusTcp */ void MyModbusTcp::connectModbusTcp() { if(!modbusDevice){ return; } if(modbusDevice->state() != QModbusDevice::ConnectedState){ modbusDevice->setConnectionParameter(QModbusClient::NetworkAddressParameter,"192.168.9.71"); modbusDevice->setConnectionParameter(QModbusClient::NetworkPortParameter,502); modbusDevice->setTimeout(2000); //设置超时 modbusDevice->setNumberOfRetries(3); //重试 if(!modbusDevice->connectDevice()){ qDebug()<<"连接失败"; } else { qDebug()<<"连接成功"; } }else{ // QMessageBox::information(this, "提示", "ModBusTcp已经连接"); return; } } /** * @brief MyModbusTcp::disconnectModbusTcp 断开连接 */ void MyModbusTcp::disconnectModbusTcp() { if(modbusDevice->state() != QModbusDevice::ConnectedState){ // QMessageBox::critical(this, "错误", "MosBusTcp未连接"); return; } modbusDevice->disconnectDevice(); qDebug()<<"ModBusTCP断开连接"; // ui->stageShwoPlain->appendPlainText("与下位机断开连接成功!"); } //===========================================数据发送、接收====================== /** * @brief MyModbusTcp::writeSingleFloat 将单个float写入保持性寄存器 * @param address 写入的保持性寄存器地址 * @param dataSend 写入的数据 * @param serverID id */ void MyModbusTcp::writeSingleFloat(int address, float dataSend, int serverID = 1){ if(modbusDevice->state() != QModbusDevice::ConnectedState){ // QMessageBox::critical(this, "错误", "MosBusTcp未连接"); return; } QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,address,2); unsigned int word[2]; float2Word(dataSend, word); writeUnit.setValue(0, word[0]); writeUnit.setValue(1, word[1]); if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, serverID)) {// ui->spinBox_SerAddress->value()是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) { //接收到的响应信息是协议错误 qDebug() << "写入数据错误:" << reply->errorString(); } else if (reply->error() != QModbusDevice::NoError) { //接收到的响应消息是其它错误 qDebug() << "写入数据错误: " << reply->errorString(); }else { //接收到的消息没有错误 一般没有必要解析响应消息 const QModbusDataUnit data = reply->result(); // qDebug() << "消息数据个数:" << data.valueCount() << " :" << data.values(); } reply->deleteLater(); }); } else { // broadcast replies return immediately reply->deleteLater(); } } else { qDebug() << "sendWriteRequest Error: " << reply->errorString(); } } /** * @brief MyModbusTcp::writeSingleWord 写入单个word(int) * @param i 地址 * @param w 写入的数据 */ void MyModbusTcp::writeSingleWord(int i, int w){ QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,i,1); writeUnit.setValue(0, w); if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, 1)) {// ui->spinBox_SerAddress->value()是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) { //接收到的响应信息是协议错误 qDebug() << "写入数据错误:" << reply->errorString(); } else if (reply->error() != QModbusDevice::NoError) { //接收到的响应消息是其它错误 qDebug() << "写入数据错误: " << reply->errorString(); }else { //接收到的消息没有错误 一般没有必要解析响应消息 const QModbusDataUnit data = reply->result(); // qDebug() << "消息数据个数:" << data.valueCount() << " :" << data.values(); } reply->deleteLater(); }); } else { // broadcast replies return immediately reply->deleteLater(); } } else { qDebug() << "sendWriteRequest Error: " << reply->errorString(); } } /** * @brief MyModbusTcp::writeMultipleHR 写多个保持性寄存器HR * @param address 起始地址 * @param num 数量 * @param dataSend 写入的数组 * @param serverID id */ void MyModbusTcp::writeMultipleHR(int address, int num, float *dataSend, int serverID = 1) { if(modbusDevice->state() != QModbusDevice::ConnectedState){ // QMessageBox::critical(this, "错误", "MosBusTcp未连接"); return; } //发送数据 qDebug() << "开始发送"; QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, address, num); unsigned int word[2]; //转换后存放的数组 for(int i=0;i<6;i++){ float2Word(dataSend[i], word); qDebug() << dataSend[i]; // qDebug() <<*word; // qDebug() <<*(word+1); writeUnit.setValue(2*i,word[0]); writeUnit.setValue(2*i+1,word[1]); } if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, serverID)) {// ui->spinBox_SerAddress->value()是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) { //接收到的响应信息是协议错误 qDebug() << "写入数据错误:" << reply->errorString(); } else if (reply->error() != QModbusDevice::NoError) { //接收到的响应消息是其它错误 qDebug() << "写入数据错误: " << reply->errorString(); }else { //接收到的消息没有错误 一般没有必要解析响应消息 const QModbusDataUnit data = reply->result(); // qDebug() << "消息数据个数:" << data.valueCount() << " :" << data.values(); } reply->deleteLater(); }); } else { // broadcast replies return immediately reply->deleteLater(); } } else { qDebug() << "sendWriteRequest Error: " ; } } /** * @brief MyModbusTcp::readMultipleHR 读取数据并放到wordRCV数组中 * @param startAddress 起始地址 * @param num 数量 * @param serverID id */ void MyModbusTcp::readMultipleHR(int startAddress, int num, int serverID = 1){ if(modbusDevice->state() != QModbusDevice::ConnectedState){ // QMessageBox::critical(this, "错误", "MosBusTcp未连接"); return; } QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, startAddress, num); //地址 if(auto *reply = modbusDevice->sendReadRequest(data, serverID)){ //发送请求 if(!reply->isFinished()){ connect(reply,&QModbusReply::finished, this, &MyModbusTcp::onReadReadyHR_Slot); } else{ delete reply; } } } /** * @brief MyModbusTcp::onReadReadyHR_Slot 读取保持性寄存器数据并放到dataRCV数组中 */ void MyModbusTcp:: onReadReadyHR_Slot(){ if(modbusDevice->state() != QModbusDevice::ConnectedState){ // QMessageBox::critical(this, "错误", "MosBusTcp未连接"); return; } QModbusReply *reply = qobject_cast(sender()); if(!reply) return; if(reply->error() == QModbusDevice::NoError){ const QModbusDataUnit responseData = reply->result(); //接收的数据 for(uint i = 0;ierror() == QModbusDevice::ProtocolError) { qDebug()<<"协议错误"; qDebug()<<"protocol error:"<errorString(); } else{ qDebug()<<"回复错误"; qDebug()<<"error:"<errorString(); } reply->deleteLater(); } //=======================定时获取数据============================== /** * @brief MyModbusTcp::onTimeReadHR 定时读HR,并保存到dataRCV数组中 */ //void MyModbusTcp::onTimeReadHR() //{ // qDebug()<<"开始持续获取plc数据"; // timer = new QTimer(this); //启动定时器,100ms // connect(timer, SIGNAL(timeout()), this, SLOT(readMultipleHR())); // timer->start(1000); // 每隔1000ms //} ///** // * @brief MyModbusTcp::stopOnTimeReadHR 停止获取数据 // */ //void MyModbusTcp::stopOnTimeReadHR() //{ // qDebug()<<"停止获取plc数据"; // timer->stop(); // timer->deleteLater(); //} //================================等待时间========================= ///** // * @brief MyModbusTcp::waitTime 等待tms // * @param time // * @param t // */ //void MyModbusTcp::waitTime(QTime time, int t){ // time.start(); //设定time为当前时间 // while(time.elapsed() < t){ //等待时间流逝500ms // QCoreApplication::processEvents(); //处理事件 // } //}