1. 程式人生 > 其它 >QT串列埠 QSerialPort類的使用

QT串列埠 QSerialPort類的使用

一、串列埠介紹

1.波特率

衡量通訊速度的引數,表示每秒鐘傳送的bit的個數。例如9600波特表示每秒鐘傳送9600個bit。常見的波特率:9600(QSerialPort::Baud9600),19200(QSerialPort::Baud19200),38400(QSerialPort::Baud38400),115200(QSerialPort::Baud115200)

2.資料位

衡量通訊中實際資料位的引數,當計算機發送一個資訊包,實際包含的有效資料位個數。常見設定:5(QSerialPort::Data5),6(QSerialPort::Data6),7(QSerialPort::Data7),8(QSerialPort::Data8)

3.停止位

用於表示單個包的最後一位。典型的值為1和2位。常見設定:1(QSerialPort::OneStop),1.5(QSerialPort::OneAndHalfStop),2(QSerialPort::TwoStop)

4.奇偶校驗位

串列埠通訊中一種檢錯方式。常用的檢錯方式有:偶、奇校驗。常見設定:None(QSerialPort::NoParity),Even(QSerialPort::EvenParity),Odd(QSerialPort::OddParity)等

5.流控

QT上還提供設定資料流控

注:串列埠資料流控

轉載:https://blog.csdn.net/lijia11080117/article/details/51371893

1.流控制在序列通訊中的作用

這裡講到的“流”,當然指的是資料流。資料在兩個串列埠之間傳輸時,常常會出現丟失資料的現象,或者兩臺計算機的處理速度不同,如桌上型電腦與微控制器之間的通訊,接收端資料緩衝區已滿,則此時繼續傳送來的資料就會丟失。現在我們在網路上通過modem進行資料傳輸,這個問題就尤為突出。流控制能解決這個問題,當接收端資料處理不過來時,就發出“不再接收”的訊號,傳送端就停止傳送,直到收到“可以繼續傳送”的訊號再發送資料。因此流控制可以控制資料傳輸的程序,防止資料的丟失。 pc機中常用的兩種流控制是硬體流控制(包括rts/cts、dtr/cts等)和軟體流控制xon/xoff(繼續/停止),下面分別說明。

2.硬體流控制

硬體流控制常用的有rts/cts流控制和dtr/dsr(資料終端就緒/資料設定就緒)流控制。

硬體流控制必須將相應的電纜線連上,用rts/cts(請求傳送/清除傳送)流控制時,應將通訊兩端的rts、cts線對應相連,資料終端裝置(如計算機)使用rts來起始調變解調器或其它資料通訊裝置的資料流,而資料通訊裝置(如調變解調器)則用cts來起動和暫停來自計算機的資料流。

這種硬體握手方式的過程為:我們在程式設計時根據接收端緩衝區大小設定一個高位標誌(可為緩衝區大小的75%)和一個低位標誌(可為緩衝區大小的25%),當緩衝區內資料量達到高位時,我們在接收端將cts線置低電平(送邏輯0),當傳送端的程式檢測到cts為低後,就停止傳送資料,直到接收端緩衝區的資料量低於低位而將cts置高電平。rts則用來標明接收裝置有沒有準備好接收資料。常用的流控制還有還有dtr/dsr(資料終端就緒/資料設定就緒)。

3.軟體流控制

由於電纜線的限制,我們在普通的控制通訊中一般不用硬體流控制,而用軟體流控制。一般通過xon/xoff來實現軟體流控制。常用方法是:當接收端的輸入緩衝區內資料量超過設定的高位時,就向資料傳送端發出xoff字元(十進位制的19或control-s,裝置程式設計說明書應該有詳細闡述),傳送端收到 xoff字元後就立即停止傳送資料;當接收端的輸入緩衝區內資料量低於設定的低位時,就向資料傳送端發出xon字元(十進位制的17或control- q),傳送端收到xon字元後就立即開始傳送資料。

程式碼展示

 //初始化波特率
    ui->Net_S_BaudrateCombo->addItem(tr("自定義"));
    ui->Net_S_BaudrateCombo->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
    ui->Net_S_BaudrateCombo->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
    ui->Net_S_BaudrateCombo->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
    ui->Net_S_BaudrateCombo->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);
    ui->Net_S_BaudrateCombo->setCurrentText(tr("38400"));

    //初始化資料位
    ui->Net_S_DataCombo->addItem(QStringLiteral("5"), QSerialPort::Data5);
    ui->Net_S_DataCombo->addItem(QStringLiteral("6"), QSerialPort::Data6);
    ui->Net_S_DataCombo->addItem(QStringLiteral("7"), QSerialPort::Data7);
    ui->Net_S_DataCombo->addItem(QStringLiteral("8"), QSerialPort::Data8);
    ui->Net_S_DataCombo->setCurrentText(tr("8"));

    //初始化停止位
    ui->Net_S_StopCombo->addItem(QStringLiteral("1"), QSerialPort::OneStop);
    ui->Net_S_StopCombo->addItem(tr("1.5"), QSerialPort::OneAndHalfStop);
    ui->Net_S_StopCombo->addItem(QStringLiteral("2"), QSerialPort::TwoStop);
    ui->Net_S_StopCombo->setCurrentText(tr("1"));

    //初始化校驗位
    ui->Net_S_ChkCombo->addItem(tr("None"), QSerialPort::NoParity);
    ui->Net_S_ChkCombo->addItem(tr("Even"), QSerialPort::EvenParity);
    ui->Net_S_ChkCombo->addItem(tr("Odd"), QSerialPort::OddParity);
    ui->Net_S_ChkCombo->addItem(tr("Mark"), QSerialPort::MarkParity);
    ui->Net_S_ChkCombo->addItem(tr("Space"), QSerialPort::SpaceParity);
    ui->Net_S_ChkCombo->setCurrentText(tr("None"));

    //初始化流控
    ui->Net_S_FlowCombo->addItem(tr("None"), QSerialPort::NoFlowControl);
    ui->Net_S_FlowCombo->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl);
    ui->Net_S_FlowCombo->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl);
    ui->Net_S_FlowCombo->setCurrentText(tr("None"));

    //設定波特率和讀寫方向
    qint32 baudRate;
    if (ui->Net_S_BaudrateCombo->currentIndex() == 4){
        baudRate = ui->Net_S_BaudrateCombo->currentText().toInt();
    }else{
        baudRate = static_cast<QSerialPort::BaudRate>(ui->Net_S_BaudrateCombo->itemData(ui->Net_S_BaudrateCombo->currentIndex()).toInt());
    }              
    m_serialPort->setBaudRate(baudRate,QSerialPort::AllDirections);
    //資料位
    QSerialPort::DataBits dataBits = static_cast<QSerialPort::DataBits>(ui->Net_S_DataCombo->itemData(ui->Net_S_DataCombo->currentIndex()).toInt());           
    m_serialPort->setDataBits(dataBits);
    //停止位
    QSerialPort::StopBits stopBits = static_cast<QSerialPort::StopBits>(ui->Net_S_StopCombo->itemData(ui->Net_S_StopCombo->currentIndex()).toInt());         
    m_serialPort->setStopBits(stopBits);
    //校驗位
    QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(ui->Net_S_ChkCombo->itemData(ui->Net_S_ChkCombo->currentIndex()).toInt());   
    m_serialPort->setParity(parity);
    //流控制
    QSerialPort::FlowControl flowControl = static_cast<QSerialPort::FlowControl>(ui->Net_S_FlowCombo->itemData(ui->Net_S_FlowCombo->currentIndex()).toInt());            
    m_serialPort->setFlowControl(flowControl);


初始化串列埠

1、從本機上查詢所有串列埠,並在介面顯示

QStringList list;
    QList<QSerialPortInfo> serialPortInfoList = QSerialPortInfo::availablePorts();//讀取所有可用的串列埠資訊
    int intID = 0;
    foreach(QSerialPortInfo serialPortInfo,serialPortInfoList)  //打印出埠資訊
    {
        QString strComboShow = (serialPortInfo.portName() + ":" + serialPortInfo.description());
        ui->Net_S_COMCombo->insertItem(intID,strComboShow,serialPortInfo.portName());
    }

QSerialPortInfo 類中可獲取串列埠埠的名稱,如:COM1,COM2等。還有相關串列埠描述。

2、開啟串列埠

   m_serialPort->setPortName("串列埠名字");//當前選擇的串列埠名字
   if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式嘗試開啟串列埠
   {
        QMessageBox::warning(this, "警告", "開啟串列埠失敗");
        return;
   }

3、串列埠接收資料

// 串列埠資料到來時,會觸發QSerialPort::readyRead事件,新增相應的響應函式
QObject::connect(m_serialPort, &QSerialPort::readyRead, this, &Nahai::serialReceiveData);

void serialReceiveData()
{
  QByteArray buffer = m_serialPort->readAll();
  //處理你要處理的資料

}

4、串列埠傳送資料

 if(m_serialPort->isOpen())
    {
        m_serialPort->write(baPacket,baPacket.size());//QByteArray baPacket:為你要傳送位元組陣列
    }

NOTE END