qextserialport-1.2rc库下载链接: http://www.pudn.com/Download/item/id/2298532.html

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

打印:

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 = );
~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[]={
BAUD1200,BAUD2400 ,BAUD4800,BAUD9600 ,
BAUD14400,BAUD19200,BAUD38400,BAUD56000,
BAUD57600,BAUD115200,BAUD128000, BAUD256000};
DataBitsType BitsTypes[]={DATA_5,DATA_6, DATA_7, DATA_8};
for(int i=;i<;i++)
{
ui->serial_baud->addItem(QString("%1").arg((int)RateTypes[i]),RateTypes[i]);
} for(int i=;i<;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("",STOP_1);
ui->serial_stop->addItem("1.5",STOP_1_5);
ui->serial_stop->addItem("",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";
        port->write( data.toLocal8Bit());
      }
} 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!=-)
{
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()==-)
ui->serial_name->setCurrentIndex();
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);
}
}

 

34.QT-制作串口助手(并动态检测在线串口,附带源码)的更多相关文章

  1. Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结

    Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结 1.1. 原理,主要使用像素模糊后的差别会变小1 1.2. 具体流程1 1.3. 提升性能 可以使用采样法即可..1 ...

  2. iOS 指南针的制作 附带源码

    iOS  指南针的制作  附带源码 代码下载地址: http://vdisk.weibo.com/s/HK4yE   http://pan.baidu.com/share/link?shareid=7 ...

  3. [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习)

    [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习) 在C#中,存在常见的九种集合类型:动态数组ArrayList.列表List.排序列表SortedList.哈希表HashTa ...

  4. 串口助手下载-带时间戳的串口助手-极简串口助手-V1.1 自动保存配置参数 能显示收发时间方便调试

    1.串口助手下载 2.带时间戳的串口助手,每次收发指令带上了时间戳,方便调试 3.极简串口助手 4.简单易用 高速稳定 5.每次修改的参数都能自动保存,免去了重复配置的工作 下载地址:http://w ...

  5. 福利!Python制作动态字符画(附源码)

    字符画,一种由字母.标点.汉字或其他字符组成的图画.简单的字符画是利用字符的形状代替图画的线条来构成简单的人物.事物等形象,它一般由人工制作而成:复杂的字符画通常利用占用不同数量像素的字符代替图画上不 ...

  6. 使用 SVG 制作单选和多选框动画【附源码】

    通过 JavaScript 实现 SVG 路径动画,我们可以做很多花哨的东西.今天我们要为您介绍一些复选框和单选按钮效果.实现的主要思路是隐藏原生的输入框,使用伪元素创造更具吸引力的样式,输入框被选中 ...

  7. Qt一步一步实现插件调用(附源码)

    最近手里几个项目都采用插件的方式进行开发工作,这里记录一下实现方法,给需要的同学一个参考, 在linux系统和window系统都能成功编译通过,不废话直接步骤 第一步:建立插件原型 新建一个Qt项目, ...

  8. Qt一步一步实现插件通信(附源码)

      前一章已经实现了主程序调用加载插件功能,这一章描述主程序和插件间通信功能 说道Qt的通信必须要了解信号和槽的机制原理,这里不做论述,不清楚的同学去看看信号和槽机制 不废话直接上步骤,在上一章的基础 ...

  9. java动态代理基本原理及proxy源码分析一

    本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的态度,于是对java动态代理的本质原理做了一些研究,于是便有了这个系列的文章 为了尽快进入正题,这里 ...

随机推荐

  1. InetAddress and InetSocketAddress

    1.InetAddress(包含IP地址及主机名) InetAddress is = InetAddress.getLocalHost(); /* 通过静态方法获得本机的对象 */ System.ou ...

  2. 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程)

    [源码下载] 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程) 作者:webabcd 介绍背水一 ...

  3. Senparc.Weixin.MP SDK 微信公众平台开发教程(十九):MessageHandler 的未知类型消息处理

    这是<微信开发深度解析:微信公众号.小程序高效开发秘籍>出版之后写的第一篇微信相关的文章.从这一篇开始,将介绍第一版出版之后添加或修改的功能,或者对书上内容需要做的补充. MP v14.8 ...

  4. Javascript高级编程学习笔记(72)—— 模拟事件(2)IE事件模拟

    IE中的事件模拟 低版本的IE浏览器作为前端开发的一股清流,想避过都不行 虽然低版本IE正在逐步被市场淘汰,不得不承认IE8以下的浏览器依然占了不小的份额 所以这里大概介绍IE8以下的低版本IE中的事 ...

  5. 吴恩达机器学习笔记21-正则化线性回归(Regularized Linear Regression)

    对于线性回归的求解,我们之前推导了两种学习算法:一种基于梯度下降,一种基于正规方程. 正则化线性回归的代价函数为: 如果我们要使用梯度下降法令这个代价函数最小化,因为我们未对theta0进行正则化,所 ...

  6. [Swift-2019力扣杯春季初赛]1. 易混淆数

    给定一个数字 N,当它满足以下条件的时候返回 true: 把原数字旋转180°以后得到新的数字. 如 0, 1, 6, 8, 9 旋转 180° 以后,得到了新的数字 0, 1, 9, 8, 6 . ...

  7. StringBuffer 和 StringBuilder 的 3 个区别

    StringBuffer 和 StringBuilder 它们都是可变的字符串,不过它们之间的区别是 Java 初中级面试出现几率十分高的一道题.这么简单的一道题,栈长在最近的面试过程中,却经常遇到很 ...

  8. preg_replace的一些细节

    .$pattern是数组,$replace也是数组,则中对应的 元素进行替换 php preg_replace有五个参数,有三个是必须参数 Preg_replace(mixed $pattern, m ...

  9. 解决transition动画与display冲突的几种方法

    如demo(如果没有显示,请查看源地址http://jsfiddle.net/ihardcoder/HNduT/2/)所示,基本的效果是在点击“Translate”按钮后,蓝色区域透明度变为0,然后隐 ...

  10. java提高(3)---正则表达式(2)

    正则表达式 说真的正则表达式真不好写,当我收集资料准备开始写的时候,发现收集的东西越来越多范围也越来越广,我文章的前提就是文章要清晰, 在缕清自己思路之后,我从先简后难的方式来写有关正表达式,你们如果 ...