当前位置:   article > 正文

Qt串口通讯例子(再也不用担心串口问题了)_qt串口通信示例

qt串口通信示例

       很多小伙伴们对串口编程刚上手时,不知道如何下手,本例子带大家看看一个简单的串口通讯的例子,例子是网上的demo,这里简单的介绍下:

这是我们常见的界面窗口,下面我们来解析下代码部分:

串口步骤:

* 1.设置串口参数

* 2.打开串口

* 3.读/写串口

* 4.关闭串口

  1. #ifndef SERIALPORT_H
  2. #define SERIALPORT_H
  3. #include <QMainWindow>
  4. #include <QtSerialPort/QSerialPort>
  5. #include <QtSerialPort/QSerialPortInfo>
  6. #include <QLabel>
  7. #include <QPushButton>
  8. #include <QCloseEvent>
  9. namespace Ui {
  10. class SerialPort;
  11. }
  12. class SerialPort : public QMainWindow
  13. {
  14. Q_OBJECT
  15. public:
  16. explicit SerialPort(QWidget *parent = 0);
  17. ~SerialPort();
  18. /* 初始状态栏 */
  19. void InitStatusBar(); // 初始化状态栏
  20. void SetSerState(); // 设置状态栏串口状态
  21. void SetRecvNum(); // 设置接收字节数
  22. void SetSendNum(); // 设置发送字节数
  23. /* 初始化CombBox控件 */
  24. void InitCommCmb(); // 初始化CombBox控件
  25. void SetPortNumCmb(); // 设置串口号
  26. QStringList GetEnableCommPortQt(); // 获取计算机可用串口 Qt方式
  27. QStringList GetEnableCommPortWin(); // 获取计算机可用串口 Windows API方式
  28. QString GetComm(int nIndex, bool bValue = true);
  29. void SetBaudCmb(); // 设置波特率
  30. void SetDPaityCmb(); // 设置校验位
  31. void SetDataBCmb(); // 设置数据位
  32. void SetStopBCmb(); // 设置停止位
  33. void SetStreamCmb(); // 设置流控制
  34. bool SetSerialPortParam(QSerialPort *serial); // 设置串口参数,失败返回false,成功返回true
  35. /* 父类函数重写 */
  36. void closeEvent(QCloseEvent *event);
  37. private slots:
  38. void on_baudRCmb_currentIndexChanged(int index); // 自定义波特率
  39. void on_OnOffBtn_clicked(); // 打开/断开串口
  40. void on_ReflushSerPortBtn_clicked(); // 刷新串口,重新扫描计算机可用串口
  41. void slot_RecvPortData(); // 接收串口数据
  42. void on_SendBtn_clicked(); // 发送数据
  43. void on_ClearRecvBtn_clicked(); // 清空接收区
  44. void slot_ResetNumBtn_clicked(); // 复位计数
  45. private:
  46. Ui::SerialPort *ui;
  47. /* 状态栏控件 */
  48. QLabel *m_SerStateLbl; // 串口状态
  49. QLabel *m_RecvNumLbl; // 接收字节数
  50. QLabel *m_SendNumLbl; // 发送字节数
  51. QPushButton *m_ResetNumBtn; // 复位计数按钮
  52. /* 发送、接收字节数 */
  53. uint m_nRecvNum; // 接收字节数
  54. uint m_nSendNum; // 发送字节数
  55. bool m_bOpen; // 标识串口状态
  56. QSerialPort *m_serial; // 串口通信类对象
  57. qint64 m_nReadBuffSize; // 串口缓冲区大小
  58. };
  59. #endif // SERIALPORT_H

对应 cpp:

函数初始化:

  1. SerialPort::SerialPort(QWidget *parent) :
  2. QMainWindow(parent),
  3. ui(new Ui::SerialPort)
  4. {
  5. ui->setupUi(this);
  6. this->setWindowTitle(tr("串口调试助手 Qt版 V1.0"));
  7. this->setFixedSize(this->width(), this->height());
  8. m_nRecvNum = 0;
  9. m_nSendNum = 0;
  10. m_bOpen = false;
  11. InitStatusBar();
  12. InitCommCmb();
  13. ui->OnOffBtn->setIcon(QIcon(":/pic/res/OFF.png"));
  14. ui->RecvDataEdt->setReadOnly(true);
  15. m_serial = new QSerialPort;
  16. connect(m_serial, SIGNAL(readyRead()), this, SLOT(slot_RecvPortData()));
  17. m_nReadBuffSize = 64;
  18. }

 InitStatusBar() 初始化状态栏:

  1. void SerialPort::InitStatusBar()
  2. {
  3. m_SerStateLbl = new QLabel();
  4. m_RecvNumLbl = new QLabel();
  5. m_SendNumLbl = new QLabel();
  6. m_ResetNumBtn = new QPushButton();
  7. connect(m_ResetNumBtn, SIGNAL(clicked()), this, SLOT(slot_ResetNumBtn_clicked()));
  8. m_SerStateLbl->setMinimumSize(180, 20);
  9. m_RecvNumLbl->setMinimumSize(180, 20); // 标签最小尺寸
  10. m_SendNumLbl->setMinimumSize(180, 20);
  11. ui->statusBar->addWidget(m_SerStateLbl);
  12. ui->statusBar->addWidget(m_RecvNumLbl);
  13. ui->statusBar->addWidget(m_SendNumLbl);
  14. ui->statusBar->addWidget(m_ResetNumBtn);
  15. SetSerState();
  16. SetRecvNum();
  17. SetSendNum();
  18. m_ResetNumBtn->setText(tr("复位计数"));
  19. }

 其中对应的set个个的函数:

  1. void SerialPort::SetSerState()
  2. {
  3. QString strState;
  4. if ( m_bOpen )
  5. strState = tr("打开");
  6. else
  7. strState = tr("关闭");
  8. m_SerStateLbl->setText(tr("串口状态:%1").arg(strState));
  9. }
  10. void SerialPort::SetRecvNum()
  11. {
  12. QString strRecvNum = QString::number(m_nRecvNum);
  13. m_RecvNumLbl->setText(tr("接收字节数:%1").arg(strRecvNum));
  14. }
  15. void SerialPort::SetSendNum()
  16. {
  17. QString strSendNum = QString::number(m_nSendNum);
  18. m_SendNumLbl->setText(tr("发送字节数:%1").arg(strSendNum));
  19. }

其目的在状态栏上显示对应的接收数据,并显示在状态栏上面。

InitCommCmb()  初始化CombBox

  1. void SerialPort::InitCommCmb()
  2. {
  3. SetPortNumCmb(); // 串口号
  4. SetBaudCmb(); // 波特率
  5. SetDPaityCmb(); // 校验位
  6. SetDataBCmb(); // 数据位
  7. SetStopBCmb(); // 停止位
  8. SetStreamCmb(); // 流控制
  9. }

这些函数是初始化最基本的东西:串口号,波特率,校验位,数据位,停止位,流控制(这个用的较少)

  1. // 设置串口号
  2. void SerialPort::SetPortNumCmb()
  3. {
  4. QStringList commPortList = GetEnableCommPortQt();
  5. if ( !commPortList.isEmpty() )
  6. ui->PortNumCmb->addItems(commPortList);
  7. }
  1. // 获取计算机可用串口 QSerialPort QSerialPortInfo类
  2. QStringList SerialPort::GetEnableCommPortQt()
  3. {
  4. QStringList CommPortList;
  5. foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
  6. {
  7. QSerialPort serial;
  8. serial.setPort(info);
  9. if (serial.open(QIODevice::ReadWrite))
  10. {
  11. CommPortList.append(serial.portName());
  12. serial.close();
  13. }
  14. }
  15. return CommPortList;
  16. }

 这个可以寻找当前串口号,然后添加到对应的选项框。

波特率:

  1. // 设置波特率
  2. void SerialPort::SetBaudCmb()
  3. {
  4. QStringList baudRList;
  5. baudRList.append(tr("110"));
  6. baudRList.append(tr("300"));
  7. baudRList.append(tr("600"));
  8. baudRList.append(tr("1200"));
  9. baudRList.append(tr("2400"));
  10. baudRList.append(tr("4800"));
  11. baudRList.append(tr("9600"));
  12. baudRList.append(tr("14400"));
  13. baudRList.append(tr("19200"));
  14. baudRList.append(tr("38400"));
  15. baudRList.append(tr("56000"));
  16. baudRList.append(tr("57600"));
  17. baudRList.append(tr("115200"));
  18. baudRList.append(tr("128000"));
  19. baudRList.append(tr("256000"));
  20. baudRList.append(tr("自定义"));
  21. ui->baudRCmb->addItems(baudRList);
  22. ui->baudRCmb->setCurrentIndex(6);
  23. }

校验位

  1. void SerialPort::SetDPaityCmb()
  2. {
  3. QStringList DPaityList;
  4. DPaityList.append(tr("NONE"));
  5. DPaityList.append(tr("ODD"));
  6. DPaityList.append(tr("EVEN"));
  7. DPaityList.append(tr("MARK"));
  8. DPaityList.append(tr("SPACE"));
  9. ui->DPaityCmb->addItems(DPaityList);
  10. }

 数据位:

  1. // 设置数据位
  2. void SerialPort::SetDataBCmb()
  3. {
  4. for (int i = 5; i <= 8; i++)
  5. {
  6. QString strDataB = QString::number(i);
  7. ui->DataBCmb->addItem(strDataB);
  8. }
  9. ui->DataBCmb->setCurrentIndex(3);
  10. }

停止位

  1. // 设置停止位
  2. void SerialPort::SetStopBCmb()
  3. {
  4. ui->StopBCmb->addItem(tr("1"));
  5. ui->StopBCmb->addItem(tr("1.5"));
  6. ui->StopBCmb->addItem(tr("2"));
  7. }

流控制:

  1. // 流控制
  2. void SerialPort::SetStreamCmb()
  3. {
  4. ui->FlowCtrlCmb->addItem(tr("NO"));
  5. ui->FlowCtrlCmb->addItem(tr("RTS/CTS"));
  6. ui->FlowCtrlCmb->addItem(tr("XON/XOFF"));
  7. }

初始化结束后,我们开始第二歩:

打开串口

  1. // 打开/关闭串口
  2. void SerialPort::on_OnOffBtn_clicked()
  3. {
  4. if (m_serial->isOpen()) // 已经处于打开状态,则关闭串口
  5. {
  6. m_serial->close();
  7. ui->OnOffBtn->setText(tr("打开"));
  8. ui->OnOffBtn->setIcon(QIcon(":/pic/res/OFF.png"));
  9. m_bOpen = false;
  10. SetSerState();
  11. }
  12. else // 串口处于关闭状态,打开串口
  13. {
  14. if ( !SetSerialPortParam(m_serial) )
  15. {
  16. QMessageBox::critical(this, tr("Error"), tr("串口错误!"), QMessageBox::Ok);
  17. return;
  18. }
  19. // 打开串口
  20. if ( !m_serial->open(QIODevice::ReadWrite) ) // 打开失败
  21. {
  22. QMessageBox::critical(this, tr("Error"), tr("串口不存在或者被其它程序占用!"), QMessageBox::Ok);
  23. // QString strRecv = ui->RecvDataEdt->toPlainText();
  24. // strRecv += tr("\n【Error】Can't Open COM Port!");
  25. ui->RecvDataEdt->append(tr("\n【Error】Can't Open COM Port!"));
  26. return;
  27. }
  28. // 设置串口缓冲区大小
  29. m_serial->setReadBufferSize(m_nReadBuffSize);
  30. ui->OnOffBtn->setText(tr("断开"));
  31. ui->OnOffBtn->setIcon(QIcon(":/pic/res/ON.png"));
  32. m_bOpen = true;
  33. SetSerState();
  34. }
  35. }
  1. // 设置串口参数,失败返回false,成功返回true
  2. bool SerialPort::SetSerialPortParam(QSerialPort *serial)
  3. {
  4. // 设置串口号
  5. QString strPortNum = ui->PortNumCmb->currentText();
  6. if (strPortNum == tr(""))
  7. return false;
  8. serial->setPortName(strPortNum);
  9. // 设置波特率
  10. qint32 nBaudRate = ui->baudRCmb->currentText().toInt();
  11. serial->setBaudRate(nBaudRate);
  12. // 设置奇偶校验
  13. int nParityType = ui->DPaityCmb->currentIndex();
  14. switch (nParityType)
  15. {
  16. case 0:
  17. serial->setParity(QSerialPort::NoParity);
  18. break;
  19. case 1:
  20. serial->setParity(QSerialPort::OddParity);
  21. break;
  22. case 2:
  23. serial->setParity(QSerialPort::EvenParity);
  24. break;
  25. case 3:
  26. serial->setParity(QSerialPort::MarkParity);
  27. break;
  28. case 4:
  29. serial->setParity(QSerialPort::SpaceParity);
  30. break;
  31. default:
  32. serial->setParity(QSerialPort::UnknownParity);
  33. break;
  34. }
  35. // 设置数据位
  36. int nDataBits = ui->DataBCmb->currentIndex();
  37. switch (nDataBits)
  38. {
  39. case 0:
  40. serial->setDataBits(QSerialPort::Data5);
  41. break;
  42. case 1:
  43. serial->setDataBits(QSerialPort::Data6);
  44. break;
  45. case 2:
  46. serial->setDataBits(QSerialPort::Data7);
  47. break;
  48. case 3:
  49. serial->setDataBits(QSerialPort::Data8);
  50. break;
  51. default:
  52. serial->setDataBits(QSerialPort::UnknownDataBits);
  53. break;
  54. }
  55. // 设置停止位
  56. int nStopBits = ui->StopBCmb->currentIndex();
  57. switch (nStopBits)
  58. {
  59. case 0:
  60. serial->setStopBits(QSerialPort::OneStop);
  61. break;
  62. case 1:
  63. serial->setStopBits(QSerialPort::OneAndHalfStop);
  64. break;
  65. case 2:
  66. serial->setStopBits(QSerialPort::TwoStop);
  67. break;
  68. default:
  69. serial->setStopBits(QSerialPort::UnknownStopBits);
  70. break;
  71. }
  72. // 流控制
  73. int nFlowCtrl = ui->FlowCtrlCmb->currentIndex();
  74. switch (nFlowCtrl)
  75. {
  76. case 0:
  77. serial->setFlowControl(QSerialPort::NoFlowControl);
  78. break;
  79. case 1:
  80. serial->setFlowControl(QSerialPort::HardwareControl);
  81. break;
  82. case 2:
  83. serial->setFlowControl(QSerialPort::SoftwareControl);
  84. break;
  85. default:
  86. serial->setFlowControl(QSerialPort::UnknownFlowControl);
  87. break;
  88. }
  89. return true;
  90. }

发送数据,接收数据:

  1. // 槽函数,接收串口数据
  2. void SerialPort::slot_RecvPortData()
  3. {
  4. QByteArray bytes = m_serial->readAll();
  5. if ( !bytes.isEmpty() )
  6. {
  7. QString strRecv = QString::fromLocal8Bit(bytes);
  8. ui->RecvDataEdt->append(strRecv);
  9. m_nRecvNum += bytes.count();
  10. SetRecvNum();
  11. }
  12. else
  13. ui->RecvDataEdt->setText(tr("接收数据出错!"));
  14. }
  15. // 发送数据,写串口
  16. void SerialPort::on_SendBtn_clicked()
  17. {
  18. // 串口未打开
  19. if ( !m_bOpen )
  20. {
  21. QMessageBox::warning(this, tr("Error"), tr("串口未打开,发送失败!"), QMessageBox::Ok);
  22. return;
  23. }
  24. QByteArray SendBytes = ui->SendDataEdt->toPlainText().toLocal8Bit();
  25. if ( !SendBytes.isEmpty() )
  26. {
  27. m_serial->write(SendBytes);
  28. m_nSendNum += SendBytes.count();
  29. SetSendNum();
  30. }
  31. }

这里如果想显示16进制,可以把代码给为下面:

  1. QByteArray buffer = tcpClient->readAll();
  2. int length = buffer.count();
  3. if(!buffer.isEmpty())
  4. {
  5. for(int i = 0; i<length; i++)
  6. {
  7. ui->textEdit_2->append(QString::asprintf("%0.2X ",buffer.at(i)));
  8. }
  9. // ui->textEdit_2->append(buffer.toHex()); //16进制显示出来数据
  10. }

这样输出的就是大写的16进制的数据啦。

其他槽函数

  1. // 串口关闭事件,如果窗口关闭前串口未关闭,则关闭串口
  2. void SerialPort::closeEvent(QCloseEvent *event)
  3. {
  4. if (m_serial->isOpen())
  5. m_serial->close();
  6. event->accept();
  7. }
  8. // 波特率自定义
  9. void SerialPort::on_baudRCmb_currentIndexChanged(int index)
  10. {
  11. uint nCount = ui->baudRCmb->count();
  12. if ((unsigned)index == nCount - 1)
  13. {
  14. ui->baudRCmb->setEditable(TRUE);
  15. ui->baudRCmb->setItemText(index, tr(""));
  16. }
  17. else
  18. {
  19. ui->baudRCmb->setEditable(FALSE);
  20. ui->baudRCmb->setItemText(nCount-1, tr("自定义"));
  21. }
  22. }
  23. // 刷新串口
  24. void SerialPort::on_ReflushSerPortBtn_clicked()
  25. {
  26. ui->PortNumCmb->clear();
  27. SetPortNumCmb();
  28. }
  29. // 复位计数
  30. void SerialPort::slot_ResetNumBtn_clicked()
  31. {
  32. m_nSendNum = 0;
  33. m_nRecvNum = 0;
  34. SetSendNum();
  35. SetRecvNum();
  36. }
  37. // 清空接受区
  38. void SerialPort::on_ClearRecvBtn_clicked()
  39. {
  40. ui->RecvDataEdt->setText(tr(""));
  41. }

需要例子的可以私信我,关注我。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/133050
推荐阅读
相关标签
  

闽ICP备14008679号