Qt 串口通信

概 述

Qt中提供了QSerialPort类来实现串口相关的操作,本文介绍Qt中如何使用QSerialPort类来实现串口通信。
.pro文件中添加

QT += serialport

头文件

#include <QSerialPort>
#include <QSerialPortInfo> //用于获取串口数据

实 现

一、获取串口信息
使用QSerialPortInfo::availablePorts(),获取系统上可用的串口列表。即QSerialPortInfo对象列表:QList<QSerialPortInfo>,列表中的每个QSerialPortInfo对象表示一个串行端口,可以查询端口名称、系统位置、描述等信息。

//遍历返回的QSerialPortInfo对象列表
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
    //将串口名称添加到界面下拉框中
    ui->serialName->addItem(info.portName()); 
}

二、设置串口信息
打开串口前,先对串口的相关配置进行设置,例如连接的串口名称、波特率、数据位等等。

m_serialPort->setPortName(ui->serialName->currentText()); //设置串口名称,使用界面下拉框中的串口
m_serialPort->setBaudRate(QSerialPort::Baud115200); //设置波特率
m_serialPort->setDataBits(QSerialPort::Data8); //设置数据位
m_serialPort->setStopBits(QSerialPort::OneStop); //设置停止位
m_serialPort->setParity(QSerialPort::NoParity); //设置有无校验位
m_serialPort->setFlowControl(QSerialPort::NoFlowControl); //设置流控制

三、打开串口

void MainWindow::on_serialOpenBtn_clicked()
{
    if (!m_serialPort->isOpen()) {
        if (m_serialPort->open(QIODevice::ReadWrite)) { //以读写方式打开串口
            m_serialPort->clear(); //每次打开串口,先清空一次缓冲区数据
            connect(m_serialPort, SIGNAL(readyRead()), SLOT(onReadyRead())); //连接数据读取信号槽
            qDebug() << "打开成功";
        } else {
            qDebug() << "打开失败";
        }
    } else {
        m_serialPort->clear();
        m_serialPort->close();
        qDebug() << "关闭";
    }
}

四、数据交互

//发送数据
void MainWindow::on_sendData_Btn_clicked()
{
    QByteArray data;
    
    //根据于下位机定义的协议,自定义数据内容
    //...

    qint64 writeLen = m_serialPort->write(data);
    if (writeLen == -1) {
        qDebug() << "数据发送失败";
    } else {
        qDebug() << "数据发送成功";
    }
}

//读取数据
//在打开串口时,连接的槽函数
void MainWindow::onReadyRead()
{
    //简单的读取所有数据
    QByteArray data = m_serialPort->readAll();
    qDebug() << "Data:" << data;

    //根据自定义协议,处理数据
    //...
}

注:对于复杂的通信协议,为了避免丢包等一系列问题造成的数据丢失,简单的readAll()并不能满足要求,Qt提供了以下的函数:

//返回等待读取的传入字节数。
bytesAvailable()
//从设备读取maxSize字节数据(此方法的读取,不会将数据从缓冲区取走)
peek(char *data, qint64 maxSize)
//在设备上启动新的读取事务
startTransaction()
//完成读取事务
commitTransaction()
//回滚读取事务
rollbackTransaction()

简单的示例:

void MainWindow::onReadyRead()
{
    MSG_HEAD msgHead; //自定义的协议消息头
    qint64 bytes;
    uint32_t flag; //自定义协议中的标志位
    
    while (true) {
        bytes = m_serialPort->bytesAvailable();
        if (bytes >= qint64(sizeof flag)) { //flag为自定义协议中的标志位,用于判断是否为有效的协议数据
            //peek flag长度的数据,但不从缓冲区中取出
            m_serialPort->peek(reinterpret_cast<char *>(&flag), sizeof flag);
            if (flag == FLAG) { //判断标志位,
                m_serialPort->startTransaction(); //开启事务
                m_serialPort->read(reinterpret_cast<char *>(&msgHead), sizeof(MSG_HEAD)); //读取协议消息头
                bytes -= sizeof(MSG_HEAD); //减去协议消息头长度

                if (bytes >= msgHead.msgLen) { //判断剩余数据长度是否大于协议消息体长度

                    handleAddrData(m_serialPort->read(ackHead.msgLen)); //读取消息体长度的数据

                    //数据处理
                    //...

                    m_serialPort->commitTransaction(); //提交读取事务
                    continue;
                }
                m_serialPort->rollbackTransaction(); //数据长度不足,回滚读取事务
            }
        }
        break;
    }
}

五、析构
清理缓冲区并关闭串口

if (m_serialPort->isOpen()) {
    m_serialPort->clear();
    m_serialPort->close();
}
delete m_serialPort;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352