Qt 串口通信
在Qt5之前,串口通信基本依赖于第三方库,下面是我曾接触过的串口通信类库:
名称 |
语言 |
平台 |
|
QextSerialPort |
QT C++ |
Win/Linux |
|
QSerialPort |
QT C++ |
QT5已经集成 |
|
libserial |
C++ |
Linux |
以上串口通信类库通信过程基本是一下步骤,即:打开串口 > 配置串口参数 > 收发数据。
注意,串口参数(波特率、数据位、停止位、奇偶校验、流控等)必须在串口打开之后进行配置才有效。
在使用串口接收数据时,会出现数据接收不完整的情况,这种情况很常见,尤其是在 QextSerialPort 和 QSerialPort 中,有一段时间我不得不怀疑是不是参数或者是硬件问题。后来发现这并不是异常,在通信中我依赖 readAll() 函数获取串口数据,但 readAll() 由 readyRead()信号触发,readyRead在串口读到起始标志时立即发送,并不一保证一定是当前所发数据的起始部分。因此串口通信双方通信前应制定好通信协议,规定好数据的起始于结尾标志,串口当读到完整的起始于结束标志之后,才认定读完一条完整的数据。
下面分别就这三种串口通信类库进行实例代码的编写。
QextSerialPort使用小例
QextSerialPort在Window平台下可用Win_QextSerialPort进行串口通信,下面对Win_QextSerialPort再一次封装的串口通信类SerialPort:
头文件:serialport.h
- #ifndef SERIALPORT_H
- #define SERIALPORT_H
- #include <QObject>
- /**
- * @brief 串口参数
- */
- struct SerialConfig{
- int baudRate; //波特率
- int characterSize; //传输位
- int stopBits; //停止位
- int parity; //校验位 0无校验 1奇校验 2偶校验
- //char*serialPort[20]; //设备文件名
- int flowControl; //流控
- long timeOut; //超时时间
- };
- class Win_QextSerialPort;
- /**
- * @brief 串口通信类
- */
- class SerialPort : public QObject
- {
- Q_OBJECT
- public:
- explicit SerialPort(QString portName, QObject *parent = );
- //~SerialPort();
- /**
- * @brief 串口数据大发送格式
- */
- enum SerialDataType{
- ASCLL=, //ascll方式
- HEX //二进制方式
- };
- /**
- * @brief 配置串口参数
- * @param config
- */
- void setSerila(SerialConfig *config);
- /**
- * @brief 获取串口开启状态
- * @return
- */
- bool isOpend();
- /**
- * @brief 设置数据发送方式
- * @param type
- */
- void setSerialDataType(SerialDataType type);
- signals:
- /**
- * @brief 串口获取到数据
- */
- void strSerial(QString);
- public slots:
- /**
- * @brief 开启串口
- * @param 串口参数
- * @return 是否成功打开串口
- */
- bool openSerial(SerialConfig *config);
- /**
- * @brief 关闭串口
- */
- void closeSerial();
- /**
- * @brief 写入数据到串口,系统默认是ascll方式
- * @param str 待写入数据
- */
- void writeSerial(QString str);
- private slots:
- /**
- * @brief 读取数据
- */
- void readSerial();
- private:
- /**
- * @brief 基本串口通信类
- */
- Win_QextSerialPort*serial;
- /**
- * @brief 数据发送形式
- */
- SerialDataType serialDataType;
- };
- #endif // SERIALPORT_H
源文件:serialport.cpp
- #include "serialport.h"
- #include "serial_inc/win_qextserialport.h"
- #include <QDebug>
- SerialPort::SerialPort(QString portName,QObject *parent):QObject(parent),serialDataType(HEX)
- {
- this->serial=new Win_QextSerialPort(portName, QextSerialBase::EventDriven);
- connect(serial,SIGNAL(readyRead()),this,SLOT(readSerial()));
- }
- void SerialPort::setSerila(SerialConfig *config)
- {
- //波特率
- BaudRateType baudRate;
- switch (config->baudRate) {
- case :
- baudRate=BAUD9600;
- break;
- case :
- baudRate=BAUD115200;
- break;
- default:
- baudRate=BAUD4800;
- break;
- }
- //数据位
- DataBitsType dataBits;
- switch (config->characterSize) {
- case :
- dataBits=DATA_7;
- break;
- default:
- dataBits=DATA_8;
- break;
- }
- //停止位
- StopBitsType stopBits;
- switch (config->stopBits) {
- case :
- stopBits=STOP_1;
- break;
- case :
- stopBits=STOP_2;
- break;
- default:
- stopBits=STOP_1_5;
- break;
- }
- //奇偶校验
- ParityType parity;
- switch (config->parity) {
- case :
- parity=PAR_NONE;
- break;
- case :
- parity=PAR_ODD;
- break;
- default:
- parity=PAR_EVEN;
- break;
- }
- //数据流控
- FlowType flow=FLOW_OFF;
- serial->setBaudRate(baudRate);
- serial->setDataBits(dataBits);
- serial->setStopBits(stopBits);
- serial->setParity(parity);
- serial->setFlowControl(flow);
- serial->setDtr(false);
- serial->setRts(false);
- }
- bool SerialPort::isOpend()
- {
- return this->serial!=NULL?serial->isOpen():false;
- }
- void SerialPort::setSerialDataType(SerialPort::SerialDataType type)
- {
- this->serialDataType=type;
- }
- void SerialPort::writeSerial(QString str)
- {
- if(this->serialDataType==this->ASCLL){
- serial->write(str.toLocal8Bit());
- }else{
- QByteArray b;
- b=QByteArray::fromHex(str.toUtf8());
- serial->write(b);
- }
- }
- void SerialPort::readSerial()
- {
- qDebug()<<serial->bytesAvailable();
- QString str="";
- QByteArray array=serial->readAll();
- if(this->serialDataType==SerialPort::ASCLL){
- str=QString::fromLocal8Bit(array.data());
- }else{
- array=array.toHex();
- str=QString::fromUtf8(array.data());
- }
- str=str.trimmed();
- qDebug()<<"serial get:"<<str;
- emit this->strSerial(str);
- }
- /**打开
- * @brief SerialPort::openSerial
- * @return
- */
- bool SerialPort::openSerial(SerialConfig*config)
- {
- bool isOpen=serial->open(QIODevice::ReadWrite);
- qDebug()<<"isOpen:"<<isOpen;
- //如果已经成功打开串口,则经行串口参数配置
- //这里有一个概念:串口配置必须在串口设备成功打开后才有效!
- if(isOpen){
- this->setSerila(config);
- }
- return isOpen;
- }
- void SerialPort::closeSerial()
- {
- serial->close();
- }
QSerialPort 使用小例
QSerialPort通信方式与 Win_QextSerialPort方式类似。
串口初始化代码片段:
- QSerialPort serial=new QSerialPort(this);
- connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));
- serial->setPortName("COM4");
- serial->setBaudRate();
- serial->setDataBits(QSerialPort::Data8);
- serial->setParity(QSerialPort::NoParity);
- serial->setStopBits(QSerialPort::OneStop);
- serial->setFlowControl(QSerialPort::NoFlowControl);
- if (serial->open(QIODevice::ReadWrite)) {
- qDebug()<<"yes";
- } else {
- qDebug()<<"no";
- }
数据接收函数:
- void QPort::readData()
- {
- QByteArray data = serial->readAll();
- qDebug()<<data;
- }
libserial使用小例
libserial只使用于Linux平台,下载源码后,进行编译和安装。下面是封装的串口通信类 Serial:
头文件:serial.h
- #ifndef SERIAL_H
- #define SERIAL_H
- #include "common.h"
- #include "SerialStream.h"
- #include "SerialStreamBuf.h"
- #include <QObject>
- using namespace std;
- using namespace LibSerial;
- typedef struct
- {
- int baudRate; //!<波特率
- int characterSize; //!<传输位
- int stopBits; //!<停止位
- int parity; //!校验位 0无校验 1奇校验 2偶校验
- char*serialPort; //!设备文件名
- }SerialConfig;
- class Serial : public QObject
- {
- Q_OBJECT
- public:
- explicit Serial(QObject *parent = );
- signals:
- void message(QString msg);
- public slots:
- //打开串口
- bool open(SerialConfig*config);
- void work();
- void close();
- void sendMesg(QString msg);
- private slots:
- private:
- /**
- * @brief 初始化串口数据
- * @param config
- */
- void initSerialStream(SerialConfig*config);
- /**
- * @brief 串口字节流
- */
- SerialStream serialStream;
- bool isRuning;
- };
- #endif // SERIAL_H
源文件:serial.cpp
- #include "serial.h"
- //数据开始标示
- #define SERIAL_DATA_START 2
- //数据结束标示
- #define SERIAL_DATA_END 3
- Serial::Serial(QObject *parent) :
- QObject(parent)
- {
- }
- bool Serial::open(SerialConfig *config){
- serialStream.Open(config->serialPort);
- if(!serialStream.IsOpen())
- {
- qDebug()<<"cannot open serial "<<config->serialPort;
- return false;
- }else{
- qDebug()<<"success open serial "<<config->serialPort;
- }
- initSerialStream(config);
- return true;
- }
- void Serial::work(){
- //缓存数据
- char *msg = new char[];
- int index = ;
- char next_byte ; //串口接收到的下一个字节
- this->isRuning=true;
- forever{
- //
- if(this->isRuning==false){
- break;
- }
- serialStream.get( next_byte );
- int char_num=next_byte+;
- if(char_num<){
- qDebug()<<":"<<next_byte+;
- }else{
- qDebug()<<next_byte;
- }
- if(char_num!=SERIAL_DATA_END)
- {
- if(char_num==SERIAL_DATA_START){
- index=;
- continue;
- }
- msg[index] = next_byte;
- index++;
- }
- else
- {
- msg[index] = '\0';
- index = ;
- qDebug("%s",msg);
- emit message(QString(msg).trimmed());
- }
- }
- }
- void Serial::close(){
- this->isRuning=false;
- }
- void Serial::sendMesg(QString msg)
- {
- msg.insert(,);
- msg.append();
- char*cmsg =msg.toUtf8().data();
- serialStream.write(cmsg,strlen(cmsg));
- }
- void Serial::initSerialStream(SerialConfig *config)
- {
- SerialStreamBuf::BaudRateEnum baudRate;
- switch (config->baudRate) {
- case :
- baudRate=SerialStreamBuf::BAUD_9600;
- break;
- case :
- baudRate=SerialStreamBuf::BAUD_115200;
- break;
- default:
- baudRate=SerialStreamBuf::BAUD_4800;
- break;
- }
- SerialStreamBuf::CharSizeEnum characterSize;
- switch (config->characterSize) {
- case :
- characterSize=SerialStreamBuf::CHAR_SIZE_7;
- break;
- default:
- characterSize=SerialStreamBuf::CHAR_SIZE_8;
- break;
- }
- SerialStreamBuf::ParityEnum parity;
- switch (config->characterSize) {
- case :
- parity=SerialStreamBuf::PARITY_NONE;
- break;
- case :
- parity=SerialStreamBuf::PARITY_ODD;
- break;
- default:
- parity=SerialStreamBuf::PARITY_EVEN;
- break;
- }
- serialStream.SetBaudRate(baudRate);
- serialStream.SetCharSize(characterSize);
- serialStream.SetNumOfStopBits(config->stopBits);
- serialStream.SetParity(parity);
- }
Qt 串口通信的更多相关文章
- Qt串口通信
1. Qt串口通信类QSerialPort 在Qt5的的更新中,新增了串口通信的相关接口类QSerialPort,这使得在开发者在使用Qt进行UI开发时,可以更加简单有效地实现串口通信的相关功能. 开 ...
- linux下的qt串口通信
1.linux下的qt串口通信跟windows唯一的差别就是端口号的名字,windows下面是COM,而linux是ttyUSB0的路径 2.一般情况下linux插上USB转串口线就可以在/dev/目 ...
- Linux 虚拟串口及 Qt 串口通信实例
Linux 虚拟串口及 Qt 串口通信实例 2011-06-22 17:49 佚名 互联网 字号:T | T Linux 虚拟串口及 Qt 串口通信实例是本文所要介绍的内容,在实现过程中,打开了两个伪 ...
- QT串口通信编程
QT串口编程 文件夹目录结构如下图所示 设计的示例界面如下图所示 首先在项目文件里面添加一句 QT += serialport SerialPortDemo.pro文件如下: #----------- ...
- Qt 串口通信之使用16进制发送数据的转换方式
Qt 串口通信之使用16进制发送数据的转换方式 一 概述 有时候在做上位机串口通讯时,经常需要将字符串转成16进制的形式作为发送,借此分析记录一下. 二 需求分析 //假设需要转换的字符:如下 QSt ...
- QT 串口通信 数据16进制发送
在QT中进行串口通信时,很多情况要用到发送16进制的数据.从网上找来了一段代码测试能用: static QByteArray QString2Hex(QString str) { QByteArray ...
- Qt串口通信专题教程
查看以前的教程:Qt编写串口通信程序全程图文讲解 查看Wincom和Lincom介绍:Qt跨平台串口通信软件Wincom与Lincom 下载软件,文档和源码:资源下载 ——————————————20 ...
- Qt 串口通信 高速发送出错的解决方法总结
使用网上的qextserialport-1.2类,自行开发多线程串口通信.开发的过程中,出现两个问题: 问题1:我用信号槽跨线程调用串口类MyCom 发送和接收数据,中间运行的时候,会内存错误,Q ...
- Qt串口通信接收数据不完整的解决方法
在使用串口接收数据时,当数据量大的时候会出现数据接收不完整的情况.因为串口数据获取函数readAll()由readyRead()信号触发,但readyRead()信号在串口读到起始标志时立即发送,并不 ...
随机推荐
- TC SRM 665 DIV2 A LuckyXor 暴力
LuckyXorTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description A lucky number is a positive int ...
- c# winform 把彩色图片转换为灰色的图片,变灰,灰度图片,速度很快,safe,unsafe
把彩色图片转换为灰色的图片,直接用.net接口遍历每个像素点转换的效率非常低,800K的图片65万像素我的电脑要用5分钟,而用了unsafe,速度提高了几千倍,同样的图片只用了0.几秒 附一个常用的遍 ...
- 奇妙华为3c手机, 出现安装未成功问题。
1.我会命令adb uninstall 先卸载我们有签名的安装包. 2.用开发模式在手机上执行我们的应用. 3.然后測试就把手机拿走了,就用应用管理器把我们的应用卸载了. 4.继续装我们的开发包,死活 ...
- SQL中declare申明变量
在sql语句中加入�变量. declare @local_variable data_type 声明时须要指定变量的类型, 能够使用set和select对变量进行赋值, 在sql语句中就能够使用@lo ...
- [MODX] 3. Placeholder +
A chunk may be used in many pages, different page may require different style. We can use Placeholde ...
- Android 进阶学习:事件分发机制全然解析,带你从源代码的角度彻底理解(上)
http://blog.csdn.net/guolin_blog/article/details/9097463 事实上我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客開始,就零 ...
- 第1章 游戏之乐——NIM(1)一排石子的游戏
NIM(1)一排石子的游戏 转载:编程之美-MIN(1)一排石头的游戏 1. 原题 1.1 题目 N块石头排成一行,每块石头有各自固定的位置.两个玩家依次取石头,每个玩家每次可以取其中任意一块石头,或 ...
- focusky 购买指南
升级Focusky动画演示大师 所有版本一次购买,终身使用,无限制作,免费升级.支付方式:支付宝.淘宝.银行转账.支付宝付款:点击表格中的“立即购买“进入购买页面->选择版本.数量,并填写详细的 ...
- VS VC++ 设置版本号
我并不是专职的VC++的开发者,只是有时候偶尔要开发一些C++的DLL,每当要发布新版本的时候,隔得时间长一点总会忘记了在那里设置生成文件的版本号. 在这里把VC++设置的步骤记录下来,以备忘! 设置 ...
- org.apache.hadoop.fs-BufferedFSInputStream
封装了FSInputStream package org.apache.hadoop.fs; import java.io.BufferedInputStream; import java.io.IO ...