34.QT-qextserialport第三方庫製做串口助手(並動態檢測在線串口,附帶源碼)

qextserialport-1.2rc庫下載連接: http://www.pudn.com/Download/item/id/2298532.html

1.添加源碼到工程html

將qextserialport-1.2rc.zip解壓,將解壓後的src目錄拷貝到項目裏的子目錄SerialSrc下,在項目pro文件中增長下面這行異步

include(./serialSrc/src/qextserialport.pri)函數

 

2.編譯時,顯示 'DEVICE_NOTIFY_ALL_INTERFACE_CLASSES'未定義工具

解決:ui

修改qextserialenumerator_p.h文件,將0x0500修改成0x0501,解決window下編譯提示「DEVICE_NOTIFY_ALL_INTERFACE_CLASSES」未定義錯誤。this

 

3.讀取在線串口spa

包含頭文件:線程

#include "qextserialport.h" #include "qextserialenumerator.h"

示例:code

QList<QextPortInfo> ports = QextSerialEnumerator::getPorts(); //! [1] qDebug() << "List of ports:"; //! [2]
foreach (QextPortInfo info, ports) { qDebug() << "port name:"       << info.portName;  //COMID qDebug() << "friendly name:"   << info.friendName;    //名稱 qDebug() << "physical name:"   << info.physName; qDebug() << "enumerator name:" << info.enumName; qDebug() << "vendor ID:"       << info.vendorID; qDebug() << "product ID:"      << info.productID;
qDebug()
<< "==================================="; }

打印:htm

 

4.串口庫相關使用(參考example示例)

串口有兩種模式EventDriven/Polling

EventDriven(事件驅動方式)

使用事件處理串口的讀取,一旦有數據到來,就會發出readyRead()信號,咱們能夠關聯該信號來讀取串口的數據。在事件驅動的方式下,串口的讀寫是異步的,調用讀寫函數會當即返回,它們不會凍結調用線程。

Polling (查詢方式)

讀寫函數是同步執行的,信號不能工做在這種模式下,並且有些功能也沒法實現。可是這種模式下的開銷較小。咱們須要本身創建定時器來讀取串口的數據。

 

在Windows下支持以上兩種模式,而在Linux下只支持Polling模式

 

讀取方式

若是想讀取一行有效數據時:

 if(port->canReadLine())
{
       qDebug()<<port->readLine();
}

若是想讀取全部有效數據時:

 if (port->bytesAvailable()) {
        qDebug()<<port->readAll();
    }

 

QextSerialPort類

用來描述具體的一個端口,能夠經過它的成員函數,來獲取/設置該端口的波特率,名稱,中止位等,也能夠經過該類來打開/關閉某個端口

示例:

port->setPortName("COM1");                // port是個QextSerialPort類對象
port->setBaudRate(BAUD1152000 );         
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setStopBits(StopBitsType);
port->setQueryMode(EventDriven);           //設置事件驅動模式

port->setBaudRate((BaudRateType)ui->baudRateBox->itemData(idx).toInt());

port->open(QIODevice::ReadWrite);        //打開串口
//進行操做中... ...
port->close();                         //關閉串口

 

QextSerialEnumerator類

用來統計在線串口用的,它有個成員函數getPorts(),其中上面第3節時便用到了.

它有兩個信號函數:

deviceDiscovered(const QextPortInfo &info);     
//出現有新的串口時,會觸發該信號,並將出現的串口信息存到info參數中

deviceRemoved(const QextPortInfo &info);
//當某個串口消失時,會觸發該信號,並將消失的串口信息存到info參數中

注意:上面兩個信號函數默認是不會觸發的,須要調用setUpNotifications()成員函數來開啓信號事件觸發

 

5.示例-使用EventDriven事件驅動模式製做串口助手

 

5.1 效果圖-跟下位機通訊

 

和原子的XCOM串口助手作比較

 

 

 

5.2建立UI

 

5.3 頭文件

#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui>
#include "qextserialport.h"
#include "qextserialenumerator.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT


    QextSerialPort *port;                //端口,用來描述具體的一個端口
    QextSerialEnumerator *enumerator;    //在線串口統計類

protected:
    void closeEvent(QCloseEvent *);
    void initBtn();                  //初始化按鈕
    void initComboBoxs();            //初始化下拉列表框
    void initSerial();               //初始化串口
    void Change_btn_isOn(bool ison);

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

private slots:
    void on_btn_send_clicked();         //發送數據
    void on_betn_clear_clicked();       //清除接收數據
    void on_btn_switch_clicked();       //串口開關
    void onPortAddedOrRemoved();        //刷新串口號
    void readLineData();                //讀數據
    void on_serial_name_currentIndexChanged(int index);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

5.4 源文件

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle(("簡易串口工具"));
    ui->recvEdit->setReadOnly(true);
    initBtn();
    initComboBoxs();
    initSerial();
    qApp->setStyleSheet("QComboBox::item{text-align: center; }");
}

void Widget::initBtn()                   //初始化按鈕
{
    Change_btn_isOn(false);
}

void Widget::initComboBoxs()           //初始化下拉列表框
{
    BaudRateType RateTypes[12]={
    BAUD1200,BAUD2400 ,BAUD4800,BAUD9600 ,
    BAUD14400,BAUD19200,BAUD38400,BAUD56000,
    BAUD57600,BAUD115200,BAUD128000, BAUD256000};
    DataBitsType BitsTypes[4]={DATA_5,DATA_6, DATA_7, DATA_8};
    for(int i=0;i<12;i++)
    {
        ui->serial_baud->addItem(QString("%1").arg((int)RateTypes[i]),RateTypes[i]);
    }

    for(int i=0;i<4;i++)
    {
        ui->serial_data->addItem(QString("%1").arg((int)BitsTypes[i]),BitsTypes[i]);
    }

    ui->serial_parity->addItem("",PAR_NONE);
    ui->serial_parity->addItem("奇校驗",PAR_ODD);
    ui->serial_parity->addItem("偶校驗",PAR_EVEN);

    ui->serial_stop->addItem("1",STOP_1);
    ui->serial_stop->addItem("1.5",STOP_1_5);
    ui->serial_stop->addItem("2",STOP_2);
}

void Widget::initSerial()               //初始化串口
{
    onPortAddedOrRemoved();
    enumerator = new QextSerialEnumerator();
    enumerator->setUpNotifications();

    connect(enumerator, SIGNAL(deviceDiscovered(QextPortInfo)),this, SLOT(onPortAddedOrRemoved()));  //發現有串口
    connect(enumerator, SIGNAL(deviceRemoved(QextPortInfo)), this, SLOT(onPortAddedOrRemoved()));     //發現沒有串口了

     port = new QextSerialPort(QextSerialPort::EventDriven,this);
     connect(port, SIGNAL(readyRead()), this,SLOT(readLineData()));   //鏈接信號
}

void Widget::on_btn_send_clicked()  //發送數據
{
    if (port->isOpen() && !ui->sendEdit->toPlainText().isEmpty())
      {
        QString data = ui->sendEdit->toPlainText();
        data+="\r\n";
      }
}

void Widget::on_betn_clear_clicked()//清除接收數據
{
    ui->recvEdit->clear();
}

void Widget::on_btn_switch_clicked()//串口開關
{if(!port->isOpen())     //當前未打開
    {
       Change_btn_isOn(true);
       port->setPortName(ui->serial_name->itemData(ui->serial_name->currentIndex()).toString());
       port->setBaudRate((BaudRateType)ui->serial_baud->itemData(ui->serial_baud->currentIndex()).toInt());
       port->setDataBits((DataBitsType)ui->serial_data->itemData(ui->serial_data->currentIndex()).toInt());
       port->setParity((ParityType)ui->serial_parity->itemData(ui->serial_parity->currentIndex()).toInt());
       port->setStopBits((StopBitsType)ui->serial_stop->itemData(ui->serial_stop->currentIndex()).toInt());
       port->open(QIODevice::ReadWrite);
    }
    else
    {
        Change_btn_isOn(false);
        port->close();
    }
}

void Widget::closeEvent(QCloseEvent *)
{
    if(port->isOpen())
        port->close();
}

void Widget::readLineData()                         //讀數據
{
   while(port->canReadLine()) {
        ui->recvEdit->moveCursor(QTextCursor::End);
        ui->recvEdit->insertPlainText(QString::fromLocal8Bit(port->readLine()));
    }
}

void Widget::onPortAddedOrRemoved()              //刷新串口號
{
    QString current = ui->serial_name->currentText();
    ui->serial_name->blockSignals(true);        //阻塞信號
    ui->serial_name->clear();

    foreach (QextPortInfo info, QextSerialEnumerator::getPorts())
    {
      QString friendname = info.friendName;
     int end=friendname.lastIndexOf(" ");
     if(end!=-1)
     {
         ui->serial_name->addItem(QString("%1:%2").arg(info.portName).arg(info.friendName.left(end)),info.portName);
     }
     else
     {
        ui->serial_name->addItem(QString("%1:%2").arg(info.portName).arg(info.friendName),info.portName);
     }
   }

    ui->serial_name->setCurrentIndex(ui->serial_name->findText(current));
    if(ui->serial_name->currentIndex()==-1)
        ui->serial_name->setCurrentIndex(0);
    ui->serial_name->blockSignals(false);       //關閉阻塞
}

void Widget::Change_btn_isOn(bool ison)
{
    if(!ison)
    {
        ui->btn_switch->setStyleSheet("color:blue;border: 1px solid blue");
        ui->btn_switch->setText("打開串口");
    }
    else
    {
        ui->btn_switch->setStyleSheet("color:red;border: 1px solid red");
        ui->btn_switch->setText("關閉串口");
    }
}

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

void Widget::on_serial_name_currentIndexChanged(int index)
{
    if (port->isOpen()) {           //若是是開啓的,則關閉串口
        port->close();
        Change_btn_isOn(false);
    }
}
相關文章
相關標籤/搜索