diff --git a/modbus.pro.user b/modbus.pro.user index 85caf27..8d0707a 100644 --- a/modbus.pro.user +++ b/modbus.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/serialcommunicator.cpp b/serialcommunicator.cpp index 3b1c996..a96ed10 100644 --- a/serialcommunicator.cpp +++ b/serialcommunicator.cpp @@ -25,19 +25,25 @@ SerialCommunicator::SerialCommunicator(QObject *parent) : QObject(parent) , serialPort_(new QSerialPort(this)) , recvTimer_(new QTimer(this)) , resendTimer_(new QTimer(this)) + , stationCheck_(new QTimer(this)) + , checkTimeOut_(new QTimer(this)) , comCount_(0) , maxRetry_(3) , recvTimeout_(50) , resendTimeout_(1000) + , test_(QByteArray::fromHex("010100010001AC0A")) { // 配置定时器(单次触发) recvTimer_->setSingleShot(true); resendTimer_->setSingleShot(true); + stationCheck_->setSingleShot(true); // 连接信号槽 connect(serialPort_, &QSerialPort::readyRead, this, &SerialCommunicator::onReadyRead); connect(recvTimer_, &QTimer::timeout, this, &SerialCommunicator::onRecvTimeout); connect(resendTimer_, &QTimer::timeout, this, &SerialCommunicator::onResendTimeout); + connect(stationCheck_, QTimer::timeout, this, SerialCommunicator::stationCheck); + connect(checkTimeOut_, QTimer::timeout, this, SerialCommunicator::checkTimeOut); connect(serialPort_, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleSerialError(QSerialPort::SerialPortError))); } @@ -119,6 +125,7 @@ bool SerialCommunicator::open() if (serialPort_->open(QIODevice::ReadWrite)) { emit statusChanged("串口连接成功"); + stationCheck_->start(1000); return true; } else @@ -145,8 +152,11 @@ void SerialCommunicator::close() //关闭所有定时器 recvTimer_->stop(); resendTimer_->stop(); + stationCheck_->stop(); + checkTimeOut_->stop(); // 清除可能存在的待处理数据 + emit stationConnect(false); serialPort_->clear(); // 关闭串口 @@ -175,6 +185,8 @@ void SerialCommunicator::sendData(const QByteArray &data) emit statusChanged("串口未打开,无法发送数据"); return; } + stationCheck_->stop(); + checkTimeOut_->stop(); // 保存待重发数据,初始化计数器,启动重发定时器 currentData_ = data; comCount_ = 0; @@ -233,6 +245,11 @@ bool SerialCommunicator::isOpen() const return serialPort_->isOpen(); } +void SerialCommunicator::setCheckMsg(QByteArray msg) +{ + this->test_ = msg; +} + // ====================== 私有槽函数 ====================== // /** @@ -245,10 +262,20 @@ bool SerialCommunicator::isOpen() const */ void SerialCommunicator::onReadyRead() { - // 读取数据到缓冲区 - recvBuffer_.append(serialPort_->readAll()); - //重置接收超时定时器 - recvTimer_->start(recvTimeout_); + if(checkTimeOut_->isActive() || stationCheck_->isActive()) + { + checkTimeOut_->stop(); + serialPort_->clear(); + emit stationConnect(true); + stationCheck_->start(1000); + } + else + { + // 读取数据到缓冲区 + recvBuffer_.append(serialPort_->readAll()); + //重置接收超时定时器 + recvTimer_->start(recvTimeout_); + } } /** @@ -262,6 +289,7 @@ void SerialCommunicator::onReadyRead() void SerialCommunicator::onRecvTimeout() { // 接收完成,发送完整数据信号,停止重发定时器 + stationCheck_->start(1000); resendTimer_->stop(); emit dataReceived(recvBuffer_); recvBuffer_.clear(); @@ -289,6 +317,7 @@ void SerialCommunicator::onResendTimeout() { // 达到最大重发次数,触发超时信号 resendTimer_->stop(); + stationCheck_->start(1000); emit timeoutOccurred(); } } @@ -382,3 +411,16 @@ void SerialCommunicator::handleSerialError(QSerialPort::SerialPortError error) } } + +void SerialCommunicator::stationCheck() +{ + serialPort_->write(test_); + checkTimeOut_->setSingleShot(true); + checkTimeOut_->start(200); +} + +void SerialCommunicator::checkTimeOut() +{ + emit stationConnect(false); + stationCheck_->start(1000); +} diff --git a/serialcommunicator.h b/serialcommunicator.h index f19092f..bc1ddb5 100644 --- a/serialcommunicator.h +++ b/serialcommunicator.h @@ -117,6 +117,8 @@ public: */ bool isOpen() const; + void setCheckMsg(QByteArray msg); + signals: /** * @brief 接收到完整数据信号 @@ -143,6 +145,8 @@ signals: */ void physicalDisconnected(); + void stationConnect(bool online); + private slots: /** * @brief 串口数据到达处理 @@ -168,16 +172,22 @@ private slots: */ void handleSerialError(QSerialPort::SerialPortError error); + void stationCheck(); + void checkTimeOut(); + private: QSerialPort *serialPort_; // 串口对象 QTimer *recvTimer_; // 接收完成判断定时器 QTimer *resendTimer_; // 超时重发定时器 + QTimer *stationCheck_; // 检测是否连接到从站 + QTimer *checkTimeOut_; QByteArray recvBuffer_; // 接收缓冲区 QByteArray currentData_; // 当前待重发数据 int comCount_; // 重发计数器 int maxRetry_; // 最大重发次数 int recvTimeout_; // 接收超时时间(ms) int resendTimeout_; // 重发间隔(ms) + QByteArray test_; // 串口参数 QString portName_; diff --git a/widget.cpp b/widget.cpp index bf609a1..ca9d437 100644 --- a/widget.cpp +++ b/widget.cpp @@ -56,6 +56,8 @@ Widget::Widget(QWidget *parent) : this, &Widget::onBtnBatchInputClicked); connect(ui_->line_input, &QLineEdit::textChanged, this, &Widget::onTextChanged); + connect(ui_->btn_checkmsg, &QPushButton::clicked, + this, &Widget::onBtnCheckmsgClicked); //当串口接收到完整数据后,serialComm_会发出dataReceived信号 connect(serialComm_, &SerialCommunicator::dataReceived, this, &Widget::onSerialDataReceived); @@ -68,6 +70,8 @@ Widget::Widget(QWidget *parent) : //当串口连接出现错误时(例如串口突然断开),serialComm_会发出physicalDisconnected信号 connect(serialComm_, &SerialCommunicator::physicalDisconnected, this, &Widget::sicalDisconnected); + connect(serialComm_, &SerialCommunicator::stationConnect, + this, &Widget::staionConneting); //设置默认波特率、数据位、校验位 ui_->combo_baud_rate->setCurrentIndex(3); @@ -492,6 +496,18 @@ void Widget::onTextChanged() ui_->line_number->setText(QString::number(data.size())); } +void Widget::staionConneting(bool online) +{ + if(online) + { + ui_->label_staion->setText("成功连接到从站"); + } + else + { + ui_->label_staion->setText("未连接到从站"); + } +} + /** * @brief 串口通信超时处理 * @@ -535,3 +551,17 @@ void Widget::onBtnBatchInputClicked() ui_->line_input->insert(inputData); } } + +void Widget::onBtnCheckmsgClicked() +{ + bool ok; + quint16 stationAddress = ui_->line_station_address->text().toUShort(&ok); + if (!ok || 0 == stationAddress) + { + QMessageBox::warning(this, "输入错误", "从站地址应为大于0的整数"); + return; + } + modbus_->setStation(stationAddress,0x01,0x01,0x01); + modbus_->readCoilAndReg(); + serialComm_->setCheckMsg(modbus_->sendCommand()); +} diff --git a/widget.h b/widget.h index bba776e..1806ffe 100644 --- a/widget.h +++ b/widget.h @@ -84,6 +84,8 @@ private slots: void onTextChanged(); + void staionConneting(bool online); + // 串口通信超时处理槽函数 void onSerialTimeout(); @@ -91,6 +93,8 @@ private slots: void onBtnBatchInputClicked(); + void onBtnCheckmsgClicked(); + private: Ui::Widget *ui_; // 指向用户界面的指针 SerialCommunicator *serialComm_; // 串口通信处理对象 diff --git a/widget.ui b/widget.ui index 40b5b2c..d3f9031 100644 --- a/widget.ui +++ b/widget.ui @@ -7,7 +7,7 @@ 0 0 700 - 500 + 503 @@ -309,9 +309,9 @@ 240 - 20 + 30 211 - 271 + 261 @@ -335,9 +335,9 @@ 470 - 20 + 30 221 - 271 + 261 @@ -508,6 +508,32 @@ true + + + + 251 + 1 + 241 + 30 + + + + + + + 未连接到从站 + + + + + + + 重新生成检测报文 + + + + +