You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

325 lines
12 KiB

#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"<<modbusDevice->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<QModbusReply *>(sender());
if(!reply) return;
if(reply->error() == QModbusDevice::NoError){
const QModbusDataUnit responseData = reply->result(); //接收的数据
for(uint i = 0;i<responseData.valueCount();i++){
wordRCV[i]= responseData.value(i);
}
for(uint i = 0;i<responseData.valueCount();i=i+2){
float float_data=0;
unsigned long longdata = 0;
longdata = (wordRCV[i]<< 16) + (wordRCV[i+1] << 0);
float_data = *(float*)&longdata;
dataRCV[i/2] = float_data;
}
}
else if (reply->error() == QModbusDevice::ProtocolError) {
qDebug()<<"协议错误";
qDebug()<<"protocol error:"<<reply->errorString();
}
else{
qDebug()<<"回复错误";
qDebug()<<"error:"<<reply->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(); //处理事件
// }
//}