Qt 串口通信

概 述

Qt中提供了QSerialPort類來實(shí)現(xiàn)串口相關(guān)的操作,本文介紹Qt中如何使用QSerialPort類來實(shí)現(xiàn)串口通信。
.pro文件中添加

QT += serialport

頭文件

#include <QSerialPort>
#include <QSerialPortInfo> //用于獲取串口數(shù)據(jù)

實(shí) 現(xiàn)

一到忽、獲取串口信息
使用QSerialPortInfo::availablePorts()或辖,獲取系統(tǒng)上可用的串口列表。即QSerialPortInfo對(duì)象列表:QList<QSerialPortInfo>忌堂,列表中的每個(gè)QSerialPortInfo對(duì)象表示一個(gè)串行端口,可以查詢端口名稱酗洒、系統(tǒng)位置士修、描述等信息。

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

二樱衷、設(shè)置串口信息
打開串口前棋嘲,先對(duì)串口的相關(guān)配置進(jìn)行設(shè)置,例如連接的串口名稱矩桂、波特率沸移、數(shù)據(jù)位等等。

m_serialPort->setPortName(ui->serialName->currentText()); //設(shè)置串口名稱侄榴,使用界面下拉框中的串口
m_serialPort->setBaudRate(QSerialPort::Baud115200); //設(shè)置波特率
m_serialPort->setDataBits(QSerialPort::Data8); //設(shè)置數(shù)據(jù)位
m_serialPort->setStopBits(QSerialPort::OneStop); //設(shè)置停止位
m_serialPort->setParity(QSerialPort::NoParity); //設(shè)置有無校驗(yàn)位
m_serialPort->setFlowControl(QSerialPort::NoFlowControl); //設(shè)置流控制

三雹锣、打開串口

void MainWindow::on_serialOpenBtn_clicked()
{
    if (!m_serialPort->isOpen()) {
        if (m_serialPort->open(QIODevice::ReadWrite)) { //以讀寫方式打開串口
            m_serialPort->clear(); //每次打開串口,先清空一次緩沖區(qū)數(shù)據(jù)
            connect(m_serialPort, SIGNAL(readyRead()), SLOT(onReadyRead())); //連接數(shù)據(jù)讀取信號(hào)槽
            qDebug() << "打開成功";
        } else {
            qDebug() << "打開失敗";
        }
    } else {
        m_serialPort->clear();
        m_serialPort->close();
        qDebug() << "關(guān)閉";
    }
}

四癞蚕、數(shù)據(jù)交互

//發(fā)送數(shù)據(jù)
void MainWindow::on_sendData_Btn_clicked()
{
    QByteArray data;
    
    //根據(jù)于下位機(jī)定義的協(xié)議笆制,自定義數(shù)據(jù)內(nèi)容
    //...

    qint64 writeLen = m_serialPort->write(data);
    if (writeLen == -1) {
        qDebug() << "數(shù)據(jù)發(fā)送失敗";
    } else {
        qDebug() << "數(shù)據(jù)發(fā)送成功";
    }
}

//讀取數(shù)據(jù)
//在打開串口時(shí),連接的槽函數(shù)
void MainWindow::onReadyRead()
{
    //簡(jiǎn)單的讀取所有數(shù)據(jù)
    QByteArray data = m_serialPort->readAll();
    qDebug() << "Data:" << data;

    //根據(jù)自定義協(xié)議涣达,處理數(shù)據(jù)
    //...
}

注:對(duì)于復(fù)雜的通信協(xié)議在辆,為了避免丟包等一系列問題造成的數(shù)據(jù)丟失,簡(jiǎn)單的readAll()并不能滿足要求度苔,Qt提供了以下的函數(shù):

//返回等待讀取的傳入字節(jié)數(shù)匆篓。
bytesAvailable()
//從設(shè)備讀取maxSize字節(jié)數(shù)據(jù)(此方法的讀取,不會(huì)將數(shù)據(jù)從緩沖區(qū)取走)
peek(char *data, qint64 maxSize)
//在設(shè)備上啟動(dòng)新的讀取事務(wù)
startTransaction()
//完成讀取事務(wù)
commitTransaction()
//回滾讀取事務(wù)
rollbackTransaction()

簡(jiǎn)單的示例:

void MainWindow::onReadyRead()
{
    MSG_HEAD msgHead; //自定義的協(xié)議消息頭
    qint64 bytes;
    uint32_t flag; //自定義協(xié)議中的標(biāo)志位
    
    while (true) {
        bytes = m_serialPort->bytesAvailable();
        if (bytes >= qint64(sizeof flag)) { //flag為自定義協(xié)議中的標(biāo)志位寇窑,用于判斷是否為有效的協(xié)議數(shù)據(jù)
            //peek flag長(zhǎng)度的數(shù)據(jù)鸦概,但不從緩沖區(qū)中取出
            m_serialPort->peek(reinterpret_cast<char *>(&flag), sizeof flag);
            if (flag == FLAG) { //判斷標(biāo)志位,
                m_serialPort->startTransaction(); //開啟事務(wù)
                m_serialPort->read(reinterpret_cast<char *>(&msgHead), sizeof(MSG_HEAD)); //讀取協(xié)議消息頭
                bytes -= sizeof(MSG_HEAD); //減去協(xié)議消息頭長(zhǎng)度

                if (bytes >= msgHead.msgLen) { //判斷剩余數(shù)據(jù)長(zhǎng)度是否大于協(xié)議消息體長(zhǎng)度

                    handleAddrData(m_serialPort->read(ackHead.msgLen)); //讀取消息體長(zhǎng)度的數(shù)據(jù)

                    //數(shù)據(jù)處理
                    //...

                    m_serialPort->commitTransaction(); //提交讀取事務(wù)
                    continue;
                }
                m_serialPort->rollbackTransaction(); //數(shù)據(jù)長(zhǎng)度不足,回滾讀取事務(wù)
            }
        }
        break;
    }
}

五窗市、析構(gòu)
清理緩沖區(qū)并關(guān)閉串口

if (m_serialPort->isOpen()) {
    m_serialPort->clear();
    m_serialPort->close();
}
delete m_serialPort;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末先慷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子咨察,更是在濱河造成了極大的恐慌论熙,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摄狱,死亡現(xiàn)場(chǎng)離奇詭異脓诡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)媒役,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門祝谚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人酣衷,你說我怎么就攤上這事交惯。” “怎么了穿仪?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵席爽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我牡借,道長(zhǎng),這世上最難降的妖魔是什么袭异? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任钠龙,我火速辦了婚禮,結(jié)果婚禮上御铃,老公的妹妹穿的比我還像新娘碴里。我一直安慰自己,他們只是感情好上真,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布咬腋。 她就那樣靜靜地躺著,像睡著了一般睡互。 火紅的嫁衣襯著肌膚如雪根竿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天就珠,我揣著相機(jī)與錄音寇壳,去河邊找鬼。 笑死妻怎,一個(gè)胖子當(dāng)著我的面吹牛壳炎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逼侦,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼匿辩,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼腰耙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起铲球,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤挺庞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后睬辐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挠阁,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年溯饵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侵俗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丰刊,死狀恐怖隘谣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啄巧,我是刑警寧澤寻歧,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站秩仆,受9級(jí)特大地震影響码泛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜澄耍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一噪珊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧齐莲,春花似錦痢站、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至芒填,卻和暖如春呜叫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背殿衰。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工怀偷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人播玖。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓椎工,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子维蒙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355