Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

185 рядки
4.6 KiB

  1. #include "mymodbus.h"
  2. MyModbus::MyModbus()
  3. {
  4. this->stationAddress_ = 1;
  5. this->functionCode_ = 0x01;
  6. this->startAdress_ = 256;
  7. this->length_ = 1;
  8. }
  9. void MyModbus::Set(quint16 stationAddress, quint16 functionCode, quint16 startAdress, quint16 length)
  10. {
  11. this->stationAddress_ = stationAddress;
  12. this->functionCode_ = functionCode;
  13. this->startAdress_ = startAdress;
  14. this->length_ = length;
  15. }
  16. void MyModbus::ReadCoilAndReg()
  17. {
  18. sendCommand_.clear();
  19. sendCommand_.append(stationAddress_%256);
  20. sendCommand_.append(functionCode_%256);
  21. sendCommand_.append(startAdress_/256);
  22. sendCommand_.append(startAdress_%256);
  23. sendCommand_.append(length_/256);
  24. sendCommand_.append(length_%256);
  25. quint16 temp = CalculateCrc(sendCommand_);
  26. sendCommand_.append(temp%256);
  27. sendCommand_.append(temp/256);
  28. }
  29. void MyModbus::WriteCoil(QVector<bool> &coils)
  30. {
  31. quint16 coilCount = coils.size();
  32. int byteCount = (coilCount + 7) / 8;
  33. sendCommand_.clear();
  34. sendCommand_.append(stationAddress_%256);
  35. sendCommand_.append(0x0f);
  36. sendCommand_.append(startAdress_/256);
  37. sendCommand_.append(startAdress_%256);
  38. sendCommand_.append(length_/256);
  39. sendCommand_.append(length_%256);
  40. sendCommand_.append(byteCount);
  41. for (int i = 0; i < byteCount; ++i)
  42. {
  43. quint8 byte = 0;
  44. for (int j = 0; j < 8; ++j)
  45. {
  46. int bitIndex = i * 8 + j;
  47. if (bitIndex < coils.size() && coils[bitIndex])
  48. byte |= (1 << j);
  49. }
  50. sendCommand_.append(static_cast<char>(byte));
  51. }
  52. quint16 temp = CalculateCrc(sendCommand_); //计算crc
  53. sendCommand_.append(temp%256); //加入计算的crc值
  54. sendCommand_.append(temp/256);
  55. }
  56. void MyModbus::WriteRegister(QVector<quint16> &values)
  57. {
  58. sendCommand_.clear();
  59. sendCommand_.append(stationAddress_%256);
  60. sendCommand_.append(0x10);
  61. sendCommand_.append(startAdress_/256);
  62. sendCommand_.append(startAdress_%256);
  63. sendCommand_.append(length_/256);
  64. sendCommand_.append(length_%256);
  65. sendCommand_.append(static_cast<char>(values.size() * 2));
  66. for (quint16 v : values)
  67. {
  68. sendCommand_.append(static_cast<char>((v >> 8) & 0xFF));
  69. sendCommand_.append(static_cast<char>(v & 0xFF));
  70. }
  71. quint16 temp = CalculateCrc(sendCommand_); //计算crc
  72. sendCommand_.append(temp%256); //加入计算的crc值
  73. sendCommand_.append(temp/256);
  74. }
  75. QByteArray MyModbus::SendCommand()
  76. {
  77. return sendCommand_;
  78. }
  79. QByteArray MyModbus::Receive(const QByteArray &revMessage)
  80. {
  81. receive_.clear();
  82. // 最小Modbus响应长度检查
  83. if(revMessage.size() < 4)
  84. { // 地址1 + 功能码1 + CRC2
  85. return receive_;
  86. }
  87. // 检查站地址匹配
  88. if(static_cast<quint8>(revMessage[0]) != stationAddress_)
  89. {
  90. return receive_;
  91. }
  92. // CRC校验
  93. if (!CrcCheck(revMessage))
  94. {
  95. return receive_;
  96. }
  97. this->receive_ = revMessage;
  98. return receive_;
  99. }
  100. int MyModbus::ErrorCheck()
  101. {
  102. // 异常响应最小长度检查
  103. if(receive_.size() < 5)
  104. {
  105. // 地址1 + 异常功能码1 + 异常码1 + CRC2
  106. return -1; // 特殊错误码表示协议错误
  107. }
  108. if ((receive_.at(1) & 0x80) == 0x80)
  109. {
  110. // MODBUS异常响应结构:地址 | 功能码+0x80 | 异常码 | CRC
  111. quint8 exCode = receive_.at(2);
  112. return exCode;
  113. }
  114. else
  115. {
  116. return 0;
  117. }
  118. }
  119. QVector<bool> MyModbus::AnalReadCoil()
  120. {
  121. QVector<bool> coil;
  122. if(receive_.size() < 6)
  123. {
  124. // 最小长度: 地址1 + 功能码1 + 长度1 + 数据1 + CRC2
  125. return coil;
  126. }
  127. quint8 byteCount = static_cast<quint8>(receive_[2]);
  128. for (int byteIndex = 0; byteIndex < byteCount; byteIndex++)
  129. {
  130. quint8 byteValue = static_cast<quint8>(receive_[3 + byteIndex]);
  131. // 解析每个字节的8个位
  132. for (int bitIndex = 0; bitIndex < 8; bitIndex++)
  133. {
  134. int coilIndex = byteIndex * 8 + bitIndex;
  135. if (coilIndex < length_)
  136. {
  137. bool state = byteValue & (1 << bitIndex);
  138. coil.append(state);
  139. }
  140. }
  141. }
  142. return coil;
  143. }
  144. QVector<quint16> MyModbus::AnalReadReg()
  145. {
  146. QVector<quint16> registers;
  147. if(receive_.size() < 7)
  148. {
  149. // 最小长度: 地址1 + 功能码1 + 长度1 + 数据2 + CRC2
  150. return registers;
  151. }
  152. int byteCount = receive_.at(2);
  153. QByteArray data = receive_.mid(3, byteCount);
  154. for (int i = 0; i < data.size(); i += 2)
  155. {
  156. quint16 value = (static_cast<quint8>(data[i]) << 8) | static_cast<quint8>(data[i+1]);
  157. registers.append(value);
  158. }
  159. return registers;
  160. }