Qt5串口代码实例

想起刚开始写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();

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值