• QT: 串口通信主站阻塞式实现


    1.运行结果

    2. 主程序调用

    1. #include "dialog.h"
    2. #include
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication app(argc, argv);
    6. Dialog dialog;
    7. dialog.show();
    8. return app.exec();
    9. }

     3. 对话框类实现

    //dialog.h

    1. #ifndef DIALOG_H
    2. #define DIALOG_H
    3. #include "masterthread.h"
    4. #include
    5. QT_BEGIN_NAMESPACE
    6. class QLabel;
    7. class QLineEdit;
    8. class QSpinBox;
    9. class QPushButton;
    10. class QComboBox;
    11. QT_END_NAMESPACE
    12. class Dialog : public QDialog
    13. {
    14. Q_OBJECT
    15. public:
    16. explicit Dialog(QWidget *parent = nullptr);
    17. private slots:
    18. void transaction();
    19. void showResponse(const QString &s);
    20. void processError(const QString &s);
    21. void processTimeout(const QString &s);
    22. private:
    23. void setControlsEnabled(bool enable);
    24. private:
    25. int m_transactionCount = 0;
    26. QLabel *m_serialPortLabel = nullptr;
    27. QComboBox *m_serialPortComboBox = nullptr;
    28. QLabel *m_waitResponseLabel = nullptr;
    29. QSpinBox *m_waitResponseSpinBox = nullptr;
    30. QLabel *m_requestLabel = nullptr;
    31. QLineEdit *m_requestLineEdit = nullptr;
    32. QLabel *m_trafficLabel = nullptr;
    33. QLabel *m_statusLabel = nullptr;
    34. QPushButton *m_runButton = nullptr;
    35. MasterThread m_thread;
    36. };
    37. #endif // DIALOG_H

    //dialog.cpp

    1. #include "dialog.h"
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. Dialog::Dialog(QWidget *parent) :
    10. QDialog(parent),
    11. m_serialPortLabel(new QLabel(tr("Serial port:"))),
    12. m_serialPortComboBox(new QComboBox),
    13. m_waitResponseLabel(new QLabel(tr("Wait response, msec:"))),
    14. m_waitResponseSpinBox(new QSpinBox),
    15. m_requestLabel(new QLabel(tr("Request:"))),
    16. m_requestLineEdit(new QLineEdit(tr("Who are you?"))),
    17. m_trafficLabel(new QLabel(tr("No traffic."))),
    18. m_statusLabel(new QLabel(tr("Status: Not running."))),
    19. m_runButton(new QPushButton(tr("Start")))
    20. {
    21. const auto infos = QSerialPortInfo::availablePorts();
    22. for (const QSerialPortInfo &info : infos)
    23. m_serialPortComboBox->addItem(info.portName());
    24. m_waitResponseSpinBox->setRange(0, 10000);
    25. m_waitResponseSpinBox->setValue(1000);
    26. auto mainLayout = new QGridLayout;
    27. mainLayout->addWidget(m_serialPortLabel, 0, 0);
    28. mainLayout->addWidget(m_serialPortComboBox, 0, 1);
    29. mainLayout->addWidget(m_waitResponseLabel, 1, 0);
    30. mainLayout->addWidget(m_waitResponseSpinBox, 1, 1);
    31. mainLayout->addWidget(m_runButton, 0, 2, 2, 1);
    32. mainLayout->addWidget(m_requestLabel, 2, 0);
    33. mainLayout->addWidget(m_requestLineEdit, 2, 1, 1, 3);
    34. mainLayout->addWidget(m_trafficLabel, 3, 0, 1, 4);
    35. mainLayout->addWidget(m_statusLabel, 4, 0, 1, 5);
    36. setLayout(mainLayout);
    37. setWindowTitle(tr("Blocking Master"));
    38. m_serialPortComboBox->setFocus();
    39. connect(m_runButton, &QPushButton::clicked, this, &Dialog::transaction);
    40. connect(&m_thread, &MasterThread::response, this, &Dialog::showResponse);
    41. connect(&m_thread, &MasterThread::error, this, &Dialog::processError);
    42. connect(&m_thread, &MasterThread::timeout, this, &Dialog::processTimeout);
    43. }
    44. void Dialog::transaction()
    45. {
    46. setControlsEnabled(false);
    47. m_statusLabel->setText(tr("Status: Running, connected to port %1.")
    48. .arg(m_serialPortComboBox->currentText()));
    49. m_thread.transaction(m_serialPortComboBox->currentText(),
    50. m_waitResponseSpinBox->value(),
    51. m_requestLineEdit->text());
    52. }
    53. void Dialog::showResponse(const QString &s)
    54. {
    55. setControlsEnabled(true);
    56. m_trafficLabel->setText(tr("Traffic, transaction #%1:"
    57. "\n\r-request: %2"
    58. "\n\r-response: %3")
    59. .arg(++m_transactionCount)
    60. .arg(m_requestLineEdit->text())
    61. .arg(s));
    62. }
    63. void Dialog::processError(const QString &s)
    64. {
    65. setControlsEnabled(true);
    66. m_statusLabel->setText(tr("Status: Not running, %1.").arg(s));
    67. m_trafficLabel->setText(tr("No traffic."));
    68. }
    69. void Dialog::processTimeout(const QString &s)
    70. {
    71. setControlsEnabled(true);
    72. m_statusLabel->setText(tr("Status: Running, %1.").arg(s));
    73. m_trafficLabel->setText(tr("No traffic."));
    74. }
    75. void Dialog::setControlsEnabled(bool enable)
    76. {
    77. m_runButton->setEnabled(enable);
    78. m_serialPortComboBox->setEnabled(enable);
    79. m_waitResponseSpinBox->setEnabled(enable);
    80. m_requestLineEdit->setEnabled(enable);
    81. }

    4.串口服务器线程实现

    //masterthread.h

    1. #ifndef MASTERTHREAD_H
    2. #define MASTERTHREAD_H
    3. #include
    4. #include
    5. #include
    6. class MasterThread : public QThread
    7. {
    8. Q_OBJECT
    9. public:
    10. explicit MasterThread(QObject *parent = nullptr);
    11. ~MasterThread();
    12. void transaction(const QString &portName, int waitTimeout, const QString &request);
    13. QByteArray HexStringToByteArray(QString HexString);
    14. signals:
    15. void response(const QString &s);
    16. void error(const QString &s);
    17. void timeout(const QString &s);
    18. private:
    19. void run() override;
    20. QString m_portName;
    21. QString m_request;
    22. int m_waitTimeout = 0;
    23. QMutex m_mutex;
    24. QWaitCondition m_cond;
    25. bool m_quit = false;
    26. };
    27. #endif // MASTERTHREAD_H

    //masterthread.cpp

    1. #include "masterthread.h"
    2. #include
    3. #include
    4. #include
    5. MasterThread::MasterThread(QObject *parent) :
    6. QThread(parent)
    7. {
    8. }
    9. MasterThread::~MasterThread()
    10. {
    11. m_mutex.lock();
    12. m_quit = true;
    13. m_cond.wakeOne();
    14. m_mutex.unlock();
    15. wait();
    16. }
    17. void MasterThread::transaction(const QString &portName, int waitTimeout, const QString &request)
    18. {
    19. const QMutexLocker locker(&m_mutex);
    20. m_portName = portName;
    21. m_waitTimeout = waitTimeout;
    22. m_request = request;
    23. if (!isRunning())
    24. start();
    25. else
    26. m_cond.wakeOne();
    27. }
    28. void MasterThread::run()
    29. {
    30. bool currentPortNameChanged = false;
    31. m_mutex.lock();
    32. QString currentPortName;
    33. if (currentPortName != m_portName) {
    34. currentPortName = m_portName;
    35. currentPortNameChanged = true;
    36. }
    37. int currentWaitTimeout = m_waitTimeout;
    38. QString currentRequest = m_request;
    39. m_mutex.unlock();
    40. QSerialPort serial;
    41. if (currentPortName.isEmpty()) {
    42. emit error(tr("No port name specified"));
    43. return;
    44. }
    45. while (!m_quit) {
    46. if (currentPortNameChanged) {
    47. serial.close();
    48. serial.setPortName(currentPortName);
    49. serial.setBaudRate(57600);
    50. serial.setStopBits(QSerialPort::TwoStop);
    51. if (!serial.open(QIODevice::ReadWrite)) {
    52. emit error(tr("Can't open %1, error code %2")
    53. .arg(m_portName).arg(serial.error()));
    54. return;
    55. }
    56. }
    57. // write request
    58. //const QByteArray requestData = currentRequest.toUtf8();
    59. const QByteArray requestData = HexStringToByteArray(currentRequest);
    60. serial.write(requestData);
    61. if (serial.waitForBytesWritten(m_waitTimeout)) {
    62. // read response
    63. if (serial.waitForReadyRead(currentWaitTimeout)) {
    64. QByteArray responseData = serial.readAll();
    65. while (serial.waitForReadyRead(10))
    66. responseData += serial.readAll();
    67. const QString response = QString::fromUtf8(responseData);
    68. emit this->response(response);
    69. } else {
    70. emit timeout(tr("Wait read response timeout %1")
    71. .arg(QTime::currentTime().toString()));
    72. }
    73. } else {
    74. emit timeout(tr("Wait write request timeout %1")
    75. .arg(QTime::currentTime().toString()));
    76. }
    77. m_mutex.lock();
    78. m_cond.wait(&m_mutex);
    79. if (currentPortName != m_portName) {
    80. currentPortName = m_portName;
    81. currentPortNameChanged = true;
    82. } else {
    83. currentPortNameChanged = false;
    84. }
    85. currentWaitTimeout = m_waitTimeout;
    86. currentRequest = m_request;
    87. m_mutex.unlock();
    88. }
    89. }
    90. QByteArray MasterThread::HexStringToByteArray(QString HexString)
    91. {
    92. bool ok;
    93. QByteArray ret;
    94. HexString = HexString.trimmed();
    95. HexString = HexString.simplified();
    96. QStringList sl = HexString.split(" ");
    97. foreach (QString s, sl) {
    98. if(!s.isEmpty())
    99. {
    100. char c = s.toInt(&ok,16) & 0xFF;
    101. if(ok){
    102. ret.append(c);
    103. }else{
    104. qDebug()<<"invalid hex string"<
    105. }
    106. }
    107. }
    108. //qDebug()<
    109. return ret;
    110. }

  • 相关阅读:
    java里面List<Object>转map,List<String>
    期末前端web大作业——HTML+CSS+JavaScript仿京东购物商城网页制作(7页)
    AI学习路线
    栈的压入、弹出序列
    尝试进行表格处理
    携职教育:2022下半年系统集成项目管理工程师备考常见问题
    Vue 组件间通信方式汇总,总有一款适合你( 附项目实战案例 )
    CHATGPT中国免费网页版有哪些-CHATGPT中文版网页
    【解刊】IEEE旗下Trans系列,中科院1区TOP,国人占比79.388%排名第一!(附IEEE名单)
    python 脚本 解决 windows 端口占用问题
  • 原文地址:https://blog.csdn.net/zkmrobot/article/details/128018674