Qt 串口通信(QSerialPort)

Qt 串口通信(QSerialPort)与下位机 单片机通信少不了使用串口进行通信 Qt 也提供了串口通信的类 QSerialPorth doc qt io qt 5 9 qserialport html 小伙伴们具体去看文档使用的时候在 pro 添加这句导入模块 QT serialport1 连接串口第一步就是要先获取到可连接的所有的串口的名字 QSerialPortI ava

前言:

本文讲述的 QSerialPort 是在qt5 + 版本以上才有
qt 4.x + linux 环境 请看这篇

正文

与下位机,单片机通信少不了使用串口进行通信,Qt 也提供了串口通信的类

QSerialPort

https://doc.qt.io/qt-5.9/qserialport.html //小伙伴们具体去看文档

使用的时候在 pro 添加这句导入模块 QT += serialport
1.连接串口 第一步就是 要先获取到 可连接的所有的串口的名字

QSerialPortInfo::availablePorts() [static] QList<QSerialPortInfo> QSerialPortInfo::availablePorts() Returns a list of available serial ports on the system. 返回系统上可用串行端口的列表 

QSerialPortInfo

Provides information about existing serial ports. Use the static functions to generate a list of QSerialPortInfo objects. Each QSerialPortInfo object in the list represents a single serial port and can be queried for the port name, system location, description, and manufacturer. The QSerialPortInfo class can also be used as an input parameter for the setPort() method of the QSerialPort class. See also QSerialPort. 提供关于现有串行端口的信息。 使用静态函数生成QSerialPortInfo对象列表。列表中的每个QSerialPortInfo对象表示一个串行端口,可以查询端口名称、系统位置、描述和制造商。QSerialPortInfo类还可以用作QSerialPort类的setPort()方法的输入参数。 
 //这样我们就获取到 可用的串口名字了 QStringList m_serialPortName; foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) { 
    m_serialPortName << info.portName(); qDebug()<<"serialPortName:"<<info.portName(); } 

获取到串口名字列表以后,我们需要选择一个需要连接的 (自行根据选择)

2.根据串口名字 打开串口

#include 
     QSerialPort *m_serialPort = new QSerialPort();//实例化串口类一个对象 if(m_serialPort->isOpen())//如果串口已经打开了 先给他关闭了 { 
    m_serialPort->clear(); m_serialPort->close(); } //设置串口名字 假设我们上面已经成功获取到了 并且使用第一个 m_serialPort->setPortName(m_serialPortName[0]); if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式尝试打开串口 { 
    qDebug()<<m_serialPortName[0]<<"打开失败!"; return; } //打开成功 m_serialPort->setBaudRate(QSerialPort::Baud,QSerialPort::AllDirections);//设置波特率和读写方向 m_serialPort->setDataBits(QSerialPort::Data8); //数据位为8位 m_serialPort->setFlowControl(QSerialPort::NoFlowControl);//无流控制 m_serialPort->setParity(QSerialPort::NoParity); //无校验位 m_serialPort->setStopBits(QSerialPort::OneStop); //一位停止位 //连接信号槽 当下位机发送数据QSerialPortInfo 会发送个 readyRead 信号,我们定义个槽void receiveInfo()解析数据 connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo())); 

3.下位机(单片机) ,上位机(Qt程序) 发送交互数据

 //接收单片机的数据 void receiveInfo() { 
    QByteArray info = m_serialPort->readAll(); QByteArray hexData = info.toHex(); //这里面的协议 你们自己定义就行 单片机发什么 代表什么 我们这里简单模拟一下 if(hexData == "0x10000") { 
    //do something } else if(hexData == "0x") { 
    //do something } } //向单片机发送数据 //基本和单片机交互 数据 都是16进制的 我们这里自己写一个 Qstring 转为 16进制的函数  void convertStringToHex(const QString &str, QByteArray &byteData) { 
    int hexdata,lowhexdata; int hexdatalen = 0; int len = str.length(); byteData.resize(len/2); char lstr,hstr; for(int i=0; i<len; ) { 
    //char lstr, hstr=str[i].toLatin1(); if(hstr == ' ') { 
    i++; continue; } i++; if(i >= len) break; lstr = str[i].toLatin1(); hexdata = convertCharToHex(hstr); lowhexdata = convertCharToHex(lstr); if((hexdata == 16) || (lowhexdata == 16)) break; else hexdata = hexdata*16+lowhexdata; i++; byteData[hexdatalen] = (char)hexdata; hexdatalen++; } byteData.resize(hexdatalen); } //另一个 函数 char 转为 16进制 char SerialPort::convertCharToHex(char ch) { 
    /* 0x30等于十进制的48,48也是0的ASCII值,, 1-9的ASCII值是49-57,,所以某一个值-0x30,, 就是将字符0-9转换为0-9 */ if((ch >= '0') && (ch <= '9')) return ch-0x30; else if((ch >= 'A') && (ch <= 'F')) return ch-'A'+10; else if((ch >= 'a') && (ch <= 'f')) return ch-'a'+10; else return (-1); } //写两个函数 向单片机发送数据  void sendInfo(char* info,int len){ 
    for(int i=0; i<len; ++i) { 
    printf("0x%x\n", info[i]); } m_serialPort->write(info,len);//这句是真正的给单片机发数据 用到的是QIODevice::write 具体可以看文档  } void sendInfo(const QString &info){ 
    QByteArray sendBuf; if (info.contains(" ")) { 
    info.replace(QString(" "),QString(""));//我这里是把空格去掉,根据你们定的协议来 } qDebug()<<"Write to serial: "<<info; convertStringToHex(info, sendBuf); //把QString 转换 为 hex  m_serialPort->write(sendBuf);这句是真正的给单片机发数据 用到的是QIODevice::write 具体可以看文档 } 

4.析构的时候 关闭串口

 if (m_serialPort->isOpen()) { 
    m_serialPort->close(); } delete m_serialPort; 

源码:

widget.h

#ifndef WIDGET_H #define WIDGET_H #include  
      #include  
      #include  
      #include  
      #include  
      namespace Ui { 
     class Widget; } class Widget : public QWidget { 
     Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); void initUI(); QStringList getPortNameList();//获取所有可用的串口列表 void openPort();//打开串口 public slots: void receiveInfo(); private: Ui::Widget *ui; QSerialPort* m_serialPort; //串口类 QStringList m_portNameList; QComboBox* m_PortNameComboBox; QPushButton* m_OpenPortButton; }; #endif // WIDGET_H 

widget.cpp

#include "widget.h" #include "ui_widget.h" #include  
      #include  
      Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { 
     ui->setupUi(this); m_serialPort = new QSerialPort(); initUI(); m_portNameList = getPortNameList(); m_PortNameComboBox->addItems(m_portNameList); connect(m_OpenPortButton,&QPushButton::clicked,this,&Widget::openPort); } Widget::~Widget() { 
     if (m_serialPort->isOpen()) { 
     m_serialPort->close(); } delete m_serialPort; delete ui; } void Widget::initUI() { 
     this->setWindowTitle("码农小明 test QSerialPort"); m_OpenPortButton = new QPushButton(); m_OpenPortButton->setText("打开串口"); m_PortNameComboBox = new QComboBox(); QHBoxLayout *m_layout = new QHBoxLayout(); m_layout->addWidget(m_PortNameComboBox); m_layout->addWidget(m_OpenPortButton); this->setLayout(m_layout); } QStringList Widget::getPortNameList() { 
     QStringList m_serialPortName; foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) { 
     m_serialPortName << info.portName(); qDebug()<<"serialPortName:"<<info.portName(); } return m_serialPortName; } void Widget::openPort() { 
     if(m_serialPort->isOpen())//如果串口已经打开了 先给他关闭了 { 
     m_serialPort->clear(); m_serialPort->close(); } m_serialPort->setPortName(m_PortNameComboBox->currentText());//当前选择的串口名字 if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式尝试打开串口 { 
     qDebug()<<"打开失败!"; return; } qDebug()<<"串口打开成功!"; m_serialPort->setBaudRate(QSerialPort::Baud,QSerialPort::AllDirections);//设置波特率和读写方向 m_serialPort->setDataBits(QSerialPort::Data8); //数据位为8位 m_serialPort->setFlowControl(QSerialPort::NoFlowControl);//无流控制 m_serialPort->setParity(QSerialPort::NoParity); //无校验位 m_serialPort->setStopBits(QSerialPort::OneStop); //一位停止位 connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo())); } //接收到单片机发送的数据进行解析 void Widget::receiveInfo() { 
     QByteArray info = m_serialPort->readAll(); qDebug()<<"receive info:"<<info; } 

这里写图片描述
这里写图片描述
这里写图片描述




下面处理数据的就不写了 简单的串口小demo 就完成了

如果此文章对你有帮助请点个关注点个赞,这就是我最大的鼓励 谢谢

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224077.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午12:44
下一篇 2026年3月17日 下午12:45


相关推荐

  • Redis 哨兵模式原理

    Redis 哨兵模式原理Redis 哨兵模式原理

    2026年3月19日
    2
  • [生成模型新方向]: score-based generative models

    [生成模型新方向]: score-based generative models0.前言最近(2021.6)发现了生成模型的一种新的trending范式:score-basedgenerativemodel,用一句话来介绍这种结构,就是:通过在噪声扰动后的大规模数据集(noise-perturbeddatadistributions)上学习一种scorefunctions(gradientsoflogprobabilitydensityfunctions)(得分函数,一种对梯度的对数似然估计),用朗之万进行采样得到符合训练集的样本.这种新的生成模型,

    2022年8月11日
    9
  • oracle 分页查询语句

    oracle 分页查询语句select from selectREC ROWNUMRNfrom selectt fromtablet RECwhereROWN lt num2 whereRN gt num1 若果需要对结果集进行排序 可这样写 select from

    2026年3月19日
    1
  • ICEM 网格划分技巧(21-5)「建议收藏」

    ICEM 网格划分技巧(21-5)「建议收藏」1.非结构网格划分时依托几何点和边界,因此在划分前应进行拓扑或清理2.边界层网格划分时应将最小尺寸限制尽量放低,边界层网格才能jiao’wei’guang’h

    2022年5月26日
    44
  • 旋转编码器工作原理图_编码器工作原理图解

    旋转编码器工作原理图_编码器工作原理图解一、旋转编码器的原理和特点:旋转编码器是集光机电技术于一体的速度位移传感器。当旋转编码器轴带动光栅盘旋转时,经发光元件发出的光被光栅盘狭缝切割成断续光线,并被接收元件接收产生初始信号。该信号经后继电路处理后,输出脉冲或代码信号。其特点是体积小,重量轻,品种多,功能全,频响高,分辨能力高,力矩小,耗能低,性能稳定,可靠使用寿命长等特点。1、增量式编码器增量…

    2022年10月1日
    5
  • 投影矩阵 视图模型矩阵「建议收藏」

    投影矩阵 视图模型矩阵「建议收藏」
        OpenGL在设置场景时,要用到两个矩阵:投影矩阵和模型视图矩阵通过glMatrixMode来指定下面的矩阵操作是针对哪一个矩阵进行的。
        gluLookatup,glTranslate,glRotate,glScale,glOrtho,gluPerspective等函数只根据其参数计算出一个矩阵M,然后与当前的栈顶元素T相乘;但这些函数本身不能自动找到应该对应的矩阵堆栈,你可以将它们放在任何矩阵堆栈操作中,比如可以将gluLookatup放在glMat

    2022年5月14日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号