想起刚开始写qt串口的时候,翻遍了百度都找不到一个qt5 serialport 串口的例子.现在把自己写的程序分享出来,给后人指指路.
具体的可以自行增删,我个人用了半年没有问题.
头文件:
#ifndef SERIALPORTOBJ_H
#define SERIALPORTOBJ_H
#include <QDateTime>
#include <QDebug>
#include <QMutexLocker>
#include <QObject>
#include <QSerialPort>
#include <QThread>
#include <QTimer>
class SerialPortObj : public QObject {
Q_OBJECT
public:
explicit SerialPortObj(
const QString& deviceName,
const QString& portName,
int portBaud,
const QSerialPort::Parity parity = QSerialPort::NoParity,
QObject* parent = nullptr);
~SerialPortObj();
void init();
bool isOpened() const;
bool isConnected() const;
QString deviceName() const;
private:
QSerialPort* serial_port_;
QString port_name_;
QString device_name_;
int baud_rate_;
QSerialPort::Parity parity_;
bool is_opened_;
bool is_connected_;
QMutex mutex_;
signals:
void sigReadData(const QByteArray& buffData);
public slots:
void sltStartInit();
void sltReadData();
void sltSendData(SerialPortObj* obj, const QByteArray& buffData);
private slots:
void sltHandleReadyRead();
};
#endif // SERIALPORTOBJ_H
cpp:
#include "serialportobj.h"
/**
* @brief SerialPortObj::SerialPortObj 对qt串口的封装类对象,需要创建一个QThread,并且
* 把此moveToThread(),连接started信号,再连接读数据信号槽即可读取数据.
* @param deviceName 设备名,用户可自定义
* @param portName 串口名,如"COM1"
* @param portBaud 波特率
* @param parity 校验位,默认无校验
* @param parent 父对象的指针
*/
SerialPortObj::SerialPortObj(const QString& deviceName,
const QString& portName,
int portBaud,
const QSerialPort::Parity parity,
QObject* parent)
: QObject(parent)
, serial_port_(nullptr)
, port_name_(portName)
, device_name_(deviceName)
, baud_rate_(portBaud)
, parity_(parity)
, is_opened_(false)
, is_connected_(false)
{
}
SerialPortObj::~SerialPortObj()
{
qDebug() << "destroy SerialPortObj";
if (serial_port_) {
if (serial_port_->isOpen())
serial_port_->close();
delete serial_port_;
serial_port_ = nullptr;
}
}
/**
* @brief SerialPortObj::init 对串口进行初始化
*/
void SerialPortObj::init()
{
serial_port_ = new QSerialPort(port_name_);
connect(serial_port_, SIGNAL(readyRead()), this, SLOT(sltHandleReadyRead()));
//设置波特率
serial_port_->setBaudRate(baud_rate_);
//设置校验位
serial_port_->setParity(parity_);
//设置数据位
serial_port_->setDataBits(QSerialPort::Data8);
//设置停止位
serial_port_->setStopBits(QSerialPort::OneStop);
//设置无硬件流控制
serial_port_->setFlowControl(QSerialPort::NoFlowControl);
if (serial_port_->open(QIODevice::ReadWrite)) {
qInfo() << this->deviceName() << "串口打开成功!";
is_opened_ = true;
} else {
qWarning() << this->deviceName() << " 串口打开失败!错误原因:" << serial_port_->errorString();
is_opened_ = false;
}
}
bool SerialPortObj::isOpened() const
{
return is_opened_;
}
bool SerialPortObj::isConnected() const
{
return is_connected_;
}
QString SerialPortObj::deviceName() const
{
return device_name_;
}
/**
* @brief SerialPortObj::sltHandleReadyRead 槽函数,当收到串口信号readyRead后,进行一定的延时在接收数据,以保证收到的
* 数据不会出现收到半截的情况。
* 2018.8.27 note:实际上不进行延时也可,只要接收频率>5ms亦不会出现粘包
* 2018.8.31 note:不进行延时的话,当数据包过长时会出现半包现象,所以应该加上延时
*/
void SerialPortObj::sltHandleReadyRead()
{
//启动定时器,接收10毫秒数据(根据情况设定),防止数据分成几段
QTimer::singleShot(10, Qt::PreciseTimer, this, SLOT(sltReadData()));
}
/**
* @brief SerialPortObj::sltReadData 槽函数,延时结束后,读取缓冲区的所有字节,并发出信号
*/
void SerialPortObj::sltReadData()
{
QMutexLocker locker(&mutex_); //加锁
if (serial_port_->bytesAvailable() <= 0)
return;
is_connected_ = true;
QByteArray data = serial_port_->readAll();
emit sigReadData(data);
//qDebug() << serial_port_->portName() << " "<< data.toHex() << " recv size:" << data.size();
}
/**
* @brief SerialPortObj::sltStartInit 槽函数,用于初始化串口
*/
void SerialPortObj::sltStartInit()
{
init();
}
/**
* @brief SerialPortObj::sltSendData 槽函数,用于向串口写数据,外部需要一个信号与此槽进行connect
* @param buffData 需要写入的数据
*/
void SerialPortObj::sltSendData(SerialPortObj* obj, const QByteArray& buffData)
{
QMutexLocker locker(&mutex_); //加锁
if (!buffData.isEmpty() && obj == this) {
serial_port_->write(buffData);
//qDebug() << serial_port_->portName() << "send data:" << buffData;
}
}
用法示例:
serial_port_thread_ = new QThread;
gyro_com_ = new SerialPortObj(tr("陀螺仪"), Param::gyro_port_name, Param::gyro_baud_rate);
gyro_com_->moveToThread(serial_port_thread_);
connect(gyro_com_, SIGNAL(sigReadData(QByteArray)), this, SLOT(sltGyroRecvData(QByteArray)));
connect(this, SIGNAL(sigSendData(SerialPortObj*, QByteArray)), gyro_com_, SLOT(sltSendData(SerialPortObj*, QByteArray)));
connect(serial_port_thread_, SIGNAL(started()), gyro_com_, SLOT(sltStartInit()));
connect(serial_port_thread_, SIGNAL(finished()), serial_port_thread_, SLOT(deleteLater()));
serial_port_thread_->start();