综合平台编辑器
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

125 Zeilen
3.8 KiB

  1. #include "ModbusManager.h"
  2. #include <QModbusDataUnit>
  3. #include <QModbusReply>
  4. #include <QSerialPort>
  5. #include <QVariant>
  6. ModbusManager::ModbusManager(QObject *parent)
  7. : QObject(parent)
  8. {
  9. }
  10. ModbusManager::~ModbusManager()
  11. {
  12. stopSimulation();
  13. }
  14. bool ModbusManager::startSimulation(const QString &serialPortName,
  15. int baudRate,
  16. int parity,
  17. int dataBits,
  18. int stopBits)
  19. {
  20. if (m_running) {
  21. emit logMessage("仿真已经在运行");
  22. return true;
  23. }
  24. m_modbusDevice = new QModbusRtuSerialClient(this);
  25. if (!m_modbusDevice)
  26. return false;
  27. m_modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, serialPortName);
  28. m_modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, parity);
  29. m_modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, baudRate);
  30. m_modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, dataBits);
  31. m_modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, stopBits);
  32. m_modbusDevice->setTimeout(1000);
  33. m_modbusDevice->setNumberOfRetries(3);
  34. if (!m_modbusDevice->connectDevice()) {
  35. emit logMessage("无法连接到 Modbus RTU 从站");
  36. delete m_modbusDevice;
  37. m_modbusDevice = nullptr;
  38. return false;
  39. }
  40. // 定时轮询
  41. m_pollingTimer = new QTimer(this);
  42. connect(m_pollingTimer, &QTimer::timeout, this, &ModbusManager::pollModbusCoils);
  43. m_pollingTimer->start(200); // 200毫秒轮询
  44. m_running = true;
  45. emit logMessage(QString("开始仿真:串口 ") + serialPortName);
  46. return true;
  47. }
  48. void ModbusManager::stopSimulation()
  49. {
  50. if (!m_running) return;
  51. if (m_pollingTimer) {
  52. m_pollingTimer->stop();
  53. m_pollingTimer->deleteLater();
  54. m_pollingTimer = nullptr;
  55. }
  56. if (m_modbusDevice) {
  57. m_modbusDevice->disconnectDevice();
  58. m_modbusDevice->deleteLater();
  59. m_modbusDevice = nullptr;
  60. }
  61. m_running = false;
  62. emit logMessage("停止仿真");
  63. }
  64. void ModbusManager::pollModbusCoils()
  65. {
  66. if (!m_modbusDevice) return;
  67. int startAddress = 0;
  68. int numberOfCoils = 9; // 根据需要修改
  69. QModbusDataUnit readUnit(QModbusDataUnit::Coils, startAddress, numberOfCoils);
  70. if (auto *reply = m_modbusDevice->sendReadRequest(readUnit, 1)) { // 1 = 从站ID
  71. if (!reply->isFinished()) {
  72. connect(reply, &QModbusReply::finished, this, [this, reply]() {
  73. if (reply->error() == QModbusDevice::NoError) {
  74. auto result = reply->result();
  75. for (uint i = 0; i < result.valueCount(); ++i) {
  76. int addr = result.startAddress() + i;
  77. bool val = result.value(i);
  78. if (m_coilValues.value(addr) != val) {
  79. m_coilValues[addr] = val;
  80. emit coilUpdated(addr, val);
  81. }
  82. }
  83. } else {
  84. emit logMessage("读取线圈失败: " + reply->errorString());
  85. }
  86. reply->deleteLater();
  87. });
  88. } else {
  89. reply->deleteLater();
  90. }
  91. }
  92. }
  93. void ModbusManager::writeCoil(int address, bool value)
  94. {
  95. if (!m_running || !m_modbusDevice) return;
  96. QModbusDataUnit writeUnit(QModbusDataUnit::Coils, address, 1);
  97. writeUnit.setValue(0, value);
  98. if (auto *reply = m_modbusDevice->sendWriteRequest(writeUnit, 1)) {
  99. connect(reply, &QModbusReply::finished, reply, &QObject::deleteLater);
  100. }
  101. }
  102. bool ModbusManager::isRunning() const
  103. {
  104. return m_running;
  105. }