Qt实现串口通信

Qt串口通信

简单了解一下串口通信

概念非常简单,串口按位(Bit)发送和接收字节;可以在使用一根线发送数据的同时使用另一根线接收数据。串口用于ASCII码字符的传输。通信使用3根线完成,分别是地线、发送、接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。

(1)波特率:衡量符号传输速率的参数(单位时间内载波参数变化的次数)
如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps。一般调制速率大于波特率,比如曼彻斯特编码)。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值。
(2)数据位:衡量通信中实际数据位的参数
当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。如何设置取决于你想传送的信息。
(3)停止位:表示单个包的最后一位(典型值1、1.5、2位)
停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
(4)奇偶校验位:串口通信中一种简单的检错方式(检错方式:偶、奇、高、低)
当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位

实例应用

效果图如下:

在这里插入图片描述

上代码(含注释)
在.pro文件中添加 serialport 模块
QT       += core gui serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>// 提供访问串口的功能
#include <QSerialPortInfo>//提供系统中存在的串口的信
#include <QList>
#include <QMessageBox>
#include <QDateTime>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void findFreePorts();
    bool initSerialPort();
    void sendMsg(const QString &msg);

public slots:
    void recvMsg();
    
private:
    Ui::MainWindow *ui;
    QSerialPort *serialPort;
};
#endif // MAINWINDOW_H

mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    /* 波特率设置 */
    ui->baudRate->setCurrentText("115200");

    this->serialPort = new QSerialPort;
    findFreePorts();

    /* 连接处理事件 */
    connect(ui->openCom, &QCheckBox::toggled, [=](bool checked){
        if (checked){
            initSerialPort();
            ui->btnSend->setEnabled(true);
        }else{
            /* 关闭串口 */
            this->serialPort->close();
            ui->btnSend->setEnabled(false);
            ui->openCom->setChecked(false);
        }
    });

    /* 连接数据接收信号readyRead 和 槽函数 */
    connect(this->serialPort, SIGNAL(readyRead()), this, SLOT(recvMsg()));

    /* 为发送按钮添加点击事件 */
    connect(ui->btnSend, &QPushButton::clicked, [=](){
        sendMsg(ui->message->toPlainText());
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

//寻找空闲状态串口
void MainWindow::findFreePorts(){
    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
    for (int i = 0; i < ports.size(); ++i){
        /* 如果端口被占用,就移除该端口名称 */
        if (ports.at(i).isBusy()){
            ports.removeAt(i);
            continue;
        }
        /* 依次追加到portName控件中,portName控件 为 combobox控件 */
        ui->portName->addItem(ports.at(i).portName());
    }
    if (!ports.size()){
        QMessageBox::warning(NULL,"Tip",QStringLiteral("找不到空闲串口"));
        return;
    }
}

//初始化串口
bool MainWindow::initSerialPort(){
    this->serialPort->setPortName(ui->portName->currentText());
    /* 打开串口 */
    if (!this->serialPort->open(QIODevice::ReadWrite)){
        QMessageBox::warning(NULL,"Tip",QStringLiteral("串口打开失败"));
        return false;
    }

    /* 波特率选择 */
    this->serialPort->setBaudRate(ui->baudRate->currentText().toInt());

    /* 数据位选择 */
    if (ui->dataBits->currentText().toInt() == 8){
        this->serialPort->setDataBits(QSerialPort::Data8);
    }else if (ui->dataBits->currentText().toInt() == 7){
        this->serialPort->setDataBits(QSerialPort::Data7);
    }else if (ui->dataBits->currentText().toInt() == 6){
        this->serialPort->setDataBits(QSerialPort::Data6);
    }else if (ui->dataBits->currentText().toInt() == 5){
        this->serialPort->setDataBits(QSerialPort::Data5);
    }

    /* 停止位选择 */
    if (ui->stopBits->currentText().toInt() == 1){
        this->serialPort->setStopBits(QSerialPort::OneStop);
    }else if (ui->stopBits->currentText().toInt() == 2){
        this->serialPort->setStopBits(QSerialPort::TwoStop);
    }

    /*奇偶校验*/
    if(ui->parity->currentText() == "NoParity"){
        this->serialPort->setParity(QSerialPort::NoParity);
    }else if (ui->parity->currentText() == "EvenParity"){
        this->serialPort->setParity(QSerialPort::EvenParity);
    }else if (ui->parity->currentText() == "OddParity"){
        this->serialPort->setParity(QSerialPort::OddParity);
    }
    return true;
}

/* 向串口发送信息 */
void MainWindow::sendMsg(const QString &msg){
    /* 发送数据 */
    this->serialPort->write(QByteArray::fromHex(msg.toLatin1()));
    ui->comLog->insertPlainText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + " [send] " + msg + "\n");
}

/* 接受来自串口的信息 */
void MainWindow::recvMsg(){
    /* 从接收缓存区中读取数据 */
    QByteArray msg = this->serialPort->readAll();
    /* 显示到控件中 */
    ui->comLog->insertPlainText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + " [recieve] " + msg.toHex().data() + "\n");
}

mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>660</width>
    <height>494</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Qt串口通信</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QGroupBox" name="groupBox">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>361</width>
      <height>351</height>
     </rect>
    </property>
    <property name="title">
     <string>通信日志</string>
    </property>
    <widget class="QTextBrowser" name="comLog">
     <property name="geometry">
      <rect>
       <x>10</x>
       <y>20</y>
       <width>341</width>
       <height>321</height>
      </rect>
     </property>
    </widget>
   </widget>
   <widget class="QGroupBox" name="groupBox_2">
    <property name="geometry">
     <rect>
      <x>380</x>
      <y>10</y>
      <width>271</width>
      <height>351</height>
     </rect>
    </property>
    <property name="title">
     <string>串口参数</string>
    </property>
    <widget class="QCheckBox" name="openCom">
     <property name="geometry">
      <rect>
       <x>30</x>
       <y>300</y>
       <width>131</width>
       <height>31</height>
      </rect>
     </property>
     <property name="text">
      <string>打开串口</string>
     </property>
    </widget>
    <widget class="QWidget" name="layoutWidget">
     <property name="geometry">
      <rect>
       <x>20</x>
       <y>30</y>
       <width>231</width>
       <height>261</height>
      </rect>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
         <widget class="QLabel" name="label">
          <property name="text">
           <string>串口:</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QComboBox" name="portName"/>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout_5">
        <item>
         <widget class="QLabel" name="label_5">
          <property name="text">
           <string>数据位:</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QComboBox" name="dataBits">
          <item>
           <property name="text">
            <string>8</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>7</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>6</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>5</string>
           </property>
          </item>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout_2">
        <item>
         <widget class="QLabel" name="label_2">
          <property name="text">
           <string>波特率:</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QComboBox" name="baudRate">
          <item>
           <property name="text">
            <string>9600</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>4800</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>19200</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>38400</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>115200</string>
           </property>
          </item>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout_4">
        <item>
         <widget class="QLabel" name="label_4">
          <property name="text">
           <string>停止位:</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QComboBox" name="stopBits">
          <item>
           <property name="text">
            <string>1</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>2</string>
           </property>
          </item>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout_3">
        <item>
         <widget class="QLabel" name="label_3">
          <property name="text">
           <string>校验位:</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QComboBox" name="parity">
          <item>
           <property name="text">
            <string>NoParity</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>EvenParity</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>OddParity</string>
           </property>
          </item>
         </widget>
        </item>
       </layout>
      </item>
     </layout>
    </widget>
   </widget>
   <widget class="QGroupBox" name="groupBox_3">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>370</y>
      <width>641</width>
      <height>111</height>
     </rect>
    </property>
    <property name="title">
     <string>发送</string>
    </property>
    <widget class="QWidget" name="layoutWidget">
     <property name="geometry">
      <rect>
       <x>10</x>
       <y>20</y>
       <width>621</width>
       <height>81</height>
      </rect>
     </property>
     <layout class="QHBoxLayout" name="horizontalLayout_6">
      <item>
       <widget class="QTextEdit" name="message"/>
      </item>
      <item>
       <widget class="QPushButton" name="btnSend">
        <property name="enabled">
         <bool>false</bool>
        </property>
        <property name="text">
         <string>发送</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </widget>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

在做知识整理的同时,希望对大家有所帮助!!!

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淘气の小狼人¹º²⁴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值