博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
34.QT-制作串口助手(并动态检测在线串口,附带源码)
阅读量:7272 次
发布时间:2019-06-29

本文共 7611 字,大约阅读时间需要 25 分钟。

qextserialport-1.2rc库下载链接:

1.添加源码到工程

将qextserialport-1.2rc.zip解压,将解压后的src目录拷贝到项目里的子目录SerialSrc下,在项目pro文件中增加下面这行

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

 

2.编译时,显示 'DEVICE_NOTIFY_ALL_INTERFACE_CLASSES'未定义

解决:

修改qextserialenumerator_p.h文件,将0x0500修改为0x0501,解决window下编译提示“DEVICE_NOTIFY_ALL_INTERFACE_CLASSES”未定义错误。

 

3.读取在线串口

包含头文件:

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

示例:

QList
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() << "==================================="; }

打印:

 

4.串口库相关使用(参考example示例)

串口有两种模式EventDriven/Polling

EventDriven(事件驱动方式)

使用事件处理串口的读取,一旦有数据到来,就会发出readyRead()信号,我们可以关联该信号来读取串口的数据。在事件驱动的方式下,串口的读写是异步的,调用读写函数会立即返回,它们不会冻结调用线程。

Polling (查询方式)

读写函数是同步执行的,信号不能工作在这种模式下,而且有些功能也无法实现。但是这种模式下的开销较小。我们需要自己建立定时器来读取串口的数据。

 

在Windows下支持以上两种模式,而在Linux下只支持Polling模式

 

读取方式

如果想读取一行有效数据时:

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

如果想读取所有有效数据时:

if (port->bytesAvailable()) {        qDebug()<
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 
#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); }}

 

 

 

 

 

 

 

转载地址:http://pmncm.baihongyu.com/

你可能感兴趣的文章
跨越南北的毕业旅行之桂林
查看>>
我的友情链接
查看>>
Centos Web 压力测试工具ApacheBench (ab)独立安装
查看>>
ImportError: No module named setuptools 解决方法
查看>>
组策略编辑器管理单元无法打开
查看>>
office 2010教程
查看>>
linux 下查找文件或者内容常有命令
查看>>
《程序员职场第一课》 - 书摘精要
查看>>
程序员必备英语单词
查看>>
WSFC2016 站点感知与健康服务
查看>>
我的敏捷布道
查看>>
nodejs小程序全面来袭(免费大放送)
查看>>
如何学习java
查看>>
效能改进之项目例会导入实践
查看>>
论测试的主要责任
查看>>
[转载]在JSTL EL中处理java.util.Map,及嵌套List的情况
查看>>
CentOS系统grub详解
查看>>
web前端安全编码
查看>>
spring boot + jta + druid整合demo
查看>>
OpenERP7.0中日期无效的问题
查看>>