当前位置: 首页 > news >正文

为什么打开串口会发送两次指令(加强版)

之前代码:
void MainWindow::on_btnSend_clicked()
{
    if (!modbusRTU || !modbusRTU->isOpen()) {
        QMessageBox::critical(this, "错误", "请先打开串口");
        return;
    }

    ui->btnSend->setEnabled(false); // 禁用按钮防止重复点击

    // 异步发送避免阻塞
    QTimer::singleShot(0, this, [this]() {
        bool ok;
        QString input = ui->txtSend->toPlainText().trimmed();
        uint16_t pressure = input.toUShort(&ok);

        if (!ok) {
            QMetaObject::invokeMethod(this, [this]() {
                QMessageBox::critical(this, "错误", "无效的压力值");
                ui->btnSend->setEnabled(true);
            });
            return;
        }

        modbusRTU->clearBuffers();
        bool success = modbusRTU->writeSingleRegister(0x0002, pressure);

        QMetaObject::invokeMethod(this, [this, success, pressure]() {
            if (success) {
                ui->txtRead->append(QString("[发送成功] 压力: %1 kPa").arg(pressure));
            } else {
                ui->txtRead->append("[发送失败] 请检查设备连接");
            }
            ui->btnSend->setEnabled(true);
        });
    });
}

之后代码:

    if (!modbusRTU || !modbusRTU->isOpen()) {
        QMessageBox::critical(this, "Error", "Serial port is not open.");
        return;
    }

    bool ok;
    QString input = ui->txtSend->toPlainText();
    uint16_t pressure = input.toUInt(&ok);

    if (!ok || input.isEmpty()) {
        QMessageBox::critical(this, "Error", "Invalid pressure value. Please enter a valid number.");
        return;
    }

    // 清理缓冲区
    modbusRTU->clearBuffers();

    // 禁用按钮,防止重复点击
    ui->btnSend->setEnabled(false);

    // 发送指令
    if (modbusRTU->writeSingleRegister(0x0002, pressure)) {
        ui->txtRead->append(QString("Set pressure to: %1 kPa").arg(pressure));
    } else {
        ui->txtRead->append("Failed to set pressure.");
    }

    // 启用按钮
    ui->btnSend->setEnabled(true);

 

改进说明

  1. 禁用按钮

    • 在发送指令之前,禁用发送按钮(ui->btnSend->setEnabled(false);),防止用户在指令发送过程中重复点击按钮。

    • 这确保了每次点击按钮时,writeSingleRegister 方法只被调用一次。

  2. 启用按钮

    • 在发送指令完成后,重新启用按钮(ui->btnSend->setEnabled(true);),以便用户可以进行下一次操作。

为什么现在可以了

通过禁用和启用按钮,确保每次点击按钮时,程序只会调用一次 writeSingleRegister 方法。这样可以避免因用户多次点击按钮而导致的重复发送指令问题。

推荐添加的改进

  1. 超时时间调整

    • 增加 waitForBytesWrittenwaitForReadyRead 方法的超时时间,确保程序有足够的时间等待数据发送和接收。

    cpp复制

    if (!serialPort->waitForBytesWritten(1000)) { // 增加超时时间到 1000 毫秒
        emit errorOccurred(QString("Timeout writing to port: %1").arg(serialPort->errorString()));
        return false;
    }
  2. 日志记录

    • 在关键步骤添加日志,记录发送和接收的数据,便于调试。

    cpp复制

    qDebug() << "Sending request:" << request.toHex();
    qDebug() << "Received response:" << response.toHex();

通过以上改进,可以确保程序只发送一次指令,并且正确处理串口通信。

相关文章:

  • JeeWMS graphReportController.do SQL注入漏洞复现(CVE-2025-0392)
  • 【OpenCV C++】以时间命名存图,自动检查存储目录,若不存在自动创建, 按下空格、回车、Q、S自动存图
  • 18440二维差分
  • 【开源-鸿蒙土拨鼠大理石系统】鸿蒙 HarmonyOS Next App+微信小程序+云平台
  • 微信小程序读取写入NFC文本,以及NFC直接启动小程序指定页面
  • AIP-155 请求标识
  • 标签使用笔记
  • sqli-lab
  • 【SpringBoot】数据访问技术spring Data、 JDBC、MyBatis、JSR-303校验
  • 使用通义万相Wan2.1进行视频生成
  • 钉钉宜搭智能车辆管理系统:AIoT与低代码融合的数字化解决方案
  • 基于Three.js的3D赛车游戏开发实战详解
  • Vue 3 路由管理实战:构建多页面博客导航 - 掌握 Vue Router 实现 SPA 页面跳转
  • nio多线程版本
  • 【Linux网络编程】五种IO模型 多路转接(select)
  • 第39天:安全开发-JavaEE应用SpringBoot框架Actuator监控泄漏Swagger自动化
  • java八股文之框架
  • (转)Java单例模式(1)
  • Unity 运用正则表达式保留字符串中的中文英文字母和数字
  • 深入理解 QVectorQString:Qt 中动态数组的强大力量
  • 宿迁做网站多少钱/黑帽seo优化推广
  • 更换网站logo/银川网页设计公司
  • 网站后台批量上传图片/网站搜索引擎优化方案
  • 家具网站开发环境与工具/2020年关键词排名
  • 025网站建设/关键词优化推广公司
  • wordpress adman/花都网络推广seo公司