Qt串口通信

环境说明 

Qt版本:5.12 Mingw32
操作系统:win10

实现的功能

与单片机之间进行串口通信,其中串口通信的程序放在子线程。

 本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

直接上代码

头文件

//myserial.h
#ifndef MYSERIAL_H
#define MYSERIAL_H
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QString>
#include <QThread>
#include <QDebug>
class mySerial : public QThread
{
    Q_OBJECT
    public:
        mySerial();
        ~mySerial();
        void SerialConnect();
        void mySerialDisconnect();
        void run();
        void setcmbPortName(QString portName);
        void setcmbBaudRate(QString baudRate);
        void setcmbDataBits(int DataBits);
        void setcmbParity(int Parity);
        void setcmbFlowControl(int FlowControl);
        void setcmbStopBits(int StopBits);
        QByteArray readAll();
        void write(QByteArray sendData_2);
public slots:
        void readComDataSlot();

signals:
    void message(const QByteArray);
    void isNotConnected();
protected:

        void handleSerialError(QSerialPort::SerialPortError error);
    private:
        QSerialPort *my_serialport;
        QString cmbPortName;
        QString cmbBaudRate;
        int cmbDataBits;
        int cmbParity;
        int cmbFlowControl;
        int cmbStopBits;
        bool disconnectbit=false;

};

#endif // MYSERIAL_H

CPP文件

//myserial.cpp
#include "myserial.h"

mySerial::mySerial()
{
    my_serialport=new QSerialPort();
}
mySerial::~mySerial()
{
    delete my_serialport;
}
void mySerial::run()
{
    while(1)
    {
        if(disconnectbit==true)
        {
            break;
        }
    }
}

void mySerial::SerialConnect()
{

        my_serialport->setPortName(cmbPortName);

        //以读写方式打开串口
        if(my_serialport->open(QIODevice::ReadWrite))
        {
            //设置波特率
            my_serialport->setBaudRate(cmbBaudRate.toInt());
            //设置数据位

            switch(cmbDataBits)
            {
                case 0:my_serialport->setDataBits(QSerialPort::Data5);break;
                case 1:my_serialport->setDataBits(QSerialPort::Data6);break;
                case 2:my_serialport->setDataBits(QSerialPort::Data7);break;
                case 3:my_serialport->setDataBits(QSerialPort::Data8);break;
            default:break;
            }
            switch(cmbParity)
            {
            case 0:my_serialport->setParity(QSerialPort::NoParity);break;
            case 1:my_serialport->setParity(QSerialPort::OddParity);break;
            case 2:my_serialport->setParity(QSerialPort::EvenParity);break;
            default:break;
            }
            //设置流控制
            switch (cmbFlowControl) {
            case 0:my_serialport->setFlowControl(QSerialPort::NoFlowControl);break;
            case 1:my_serialport->setFlowControl(QSerialPort::FlowControl());
            }
            //设置停止位
            switch(cmbStopBits)
            {
            case 0:my_serialport->setStopBits(QSerialPort::OneStop);break;
            case 1:my_serialport->setStopBits(QSerialPort::OneAndHalfStop);break;
            case 2:my_serialport->setStopBits(QSerialPort::TwoStop);break;
            }
            //每秒读一次
            connect(my_serialport, SIGNAL(readyRead()), this, SLOT(readComDataSlot()));
            connect(my_serialport, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),  this, &mySerial::handleSerialError);



        }
    else
    {
        my_serialport->close();
    }

}

void mySerial::handleSerialError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::ResourceError) {

            mySerialDisconnect();

        }
    emit isNotConnected();
}
void mySerial::readComDataSlot()
{
    //读取串口数据

    QByteArray readComData = my_serialport->readAll();
    //qDebug()<<readComData<<endl;
    //将读到的数据显示到数据接收区的te中
    if(!readComData.isNull())
    {
        message(readComData);
    }

    //清除缓冲区
    readComData.clear();
}
QByteArray mySerial::readAll()
{
    QByteArray readComData = my_serialport->readAll();
    return readComData;
}
void mySerial::write(QByteArray sendData_2)
{
    my_serialport->write(sendData_2);
}

 void mySerial::mySerialDisconnect()
{
    my_serialport->close();
}

void mySerial::setcmbPortName(QString PortName)
{
    cmbPortName=PortName;
}

void mySerial::setcmbBaudRate(QString BaudRate)
{
    cmbBaudRate=BaudRate;
}

void mySerial::setcmbDataBits(int DataBits)
{
    cmbDataBits=DataBits;
}

void mySerial::setcmbParity(int Parity)
{
    cmbParity=Parity;
}

void mySerial::setcmbFlowControl(int FlowControl)
{
    cmbFlowControl=FlowControl;
}

void mySerial::setcmbStopBits(int StopBits)
{
    cmbStopBits=StopBits;
}


//wigth.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "myserial.h"
#include <QTimer>
#include <QTime>
#include <QDebug>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void handleSerialError();
    void cmbPortNameRefresh();
    void readComDataSlot(QByteArray message);

private slots:
    void on_btnOpen_released();

    void on_btnSend_released();

    void on_clearRecive_released();

    void on_clearSend_released();

    void on_cbReceive_stateChanged(int arg1);

    void on_cbSend_stateChanged(int arg1);

    void on_teReceiveData_textChanged();

    void on_teReceiveDataHex_textChanged();

    void on_teSendData_textChanged();

    void on_teSendDataHex_textChanged();

private:
    Ui::Widget *ui;
    QTimer *timer;
    mySerial *my_serialport;
    bool state=false;
    QString beforeport;
    bool HexState=false;
    bool TimeState=false;
    bool receiveStat=true;
    bool sendStat=true;
    bool SendStat=true;

    void portRefresh();
    QString ByteArrayToHexString(QByteArray data);
    QString  getCurrentTime();
    void initPort();
    QString deleteCharString0(QString sourceString, char chElemData);
};

#endif // WIDGET_H

//wigth.cpp
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    initPort();
    timer=new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(cmbPortNameRefresh()));
    my_serialport=new mySerial();
    connect(my_serialport,SIGNAL(message(QByteArray)),this,SLOT(readComDataSlot(QByteArray)));
    connect(my_serialport,SIGNAL(isNotConnected()),  this, SLOT(handleSerialError()));
    timer->start(1000);
    ui->teReceiveDataHex->setVisible(false);
    ui->teSendDataHex->setVisible(false);

}

void Widget::initPort()
{
    portRefresh();
    QStringList baudList;//波特率
    QStringList parityList;//校验位
    QStringList dataBitsList;//数据位
    QStringList stopBitsList;//停止位
    QStringList flowControlList;
    baudList<<"256000"<<"128000"<<"115200"<<"76800"<<"57600"<<"56000"<<"38400"
           <<"19200"<<"14400"<<"9600"<<"4800"<<"2400"<<"1800"
          <<"1200"<<"600"<<"300"<<"200"<<"134"
         <<"100"<<"75"<<"50";
    ui->cmbBaudRate->addItems(baudList);
    ui->cmbBaudRate->setCurrentIndex(9);
    parityList<<"无"<<"奇"<<"偶";
    ui->cmbParity->addItems(parityList);
    ui->cmbParity->setCurrentIndex(0);
    dataBitsList<<"5"<<"6"<<"7"<<"8";
    ui->cmbDataBits->addItems(dataBitsList);
    ui->cmbDataBits->setCurrentIndex(3);
    stopBitsList<<"1";
    stopBitsList<<"1.5";
    stopBitsList<<"2";
    ui->cmbStopBits->addItems(stopBitsList);
    ui->cmbStopBits->setCurrentIndex(0);
}

Widget::~Widget()
{
    delete ui;
}
void Widget::handleSerialError()
{
        ui->btnOpen->setText("打开串口");
        ui->cmbPortName->setEnabled(true);
        ui->cmbBaudRate->setEnabled(true);
        ui->cmbParity->setEnabled(true);
        ui->cmbDataBits->setEnabled(true);
        ui->cmbStopBits->setEnabled(true);
        state=false;
}
void Widget::cmbPortNameRefresh()
{
    portRefresh();
}
void Widget::portRefresh()
{
    beforeport=ui->cmbPortName->currentText();
    ui->cmbPortName->clear();
    //读取串口信息
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
            //将串口号添加到cmb
            ui->cmbPortName->addItem(info.portName());
            for ( int i = 0 ; i < ui->cmbPortName->count(); i ++ )
            {
                  if(ui->cmbPortName->itemText(i)==beforeport)
                  {
                      ui->cmbPortName->setCurrentIndex(i);
                  }
            }

    }
}

QString Widget::ByteArrayToHexString(QByteArray data){
    QString ret(data.toHex().toUpper());
    int len = ret.length()/2;
    for(int i=1;i<len;i++)
    {
        ret.insert(2*i+i-1," ");
    }

    return ret;
}


void Widget::readComDataSlot(QByteArray message)
{
    //读取串口数据
    QByteArray readComData = message;
    QString num=message;
    num=deleteCharString0(num,0x0a);
   // qDebug()<<num<<endl;
    //if(HexState==true)
    if(false)
    {
        QString date= ByteArrayToHexString(readComData);
        readComData=date.toLatin1();
    }
    //将读到的数据显示到数据接收区的te中
    if(!readComData.isNull())
    {
        ui->teReceiveData->append(readComData);
        if(TimeState)
        {
            QString time=getCurrentTime();
            ui->teReceiveData->append(time);
        }
    }

    //清除缓冲区
    readComData.clear();
}

QString  Widget::getCurrentTime()
{
    QTime current_time =QTime::currentTime();
    int hour = current_time.hour();//当前的小时
    int minute = current_time.minute();//当前的分
    int second = current_time.second();//当前的秒
    int msec = current_time.msec();//当前的毫秒
    QString time=QString::number(hour,10)+":"+QString::number(minute,10)+":"+QString::number(second,10)+":"+QString::number(msec,10);
    return time;
}

void Widget::on_btnOpen_released()
{
    timer->stop();
    if(state==false)
    {
        //设置串口号
        if(!ui->cmbPortName->currentText().isNull())
        {
        my_serialport->setcmbPortName(ui->cmbPortName->currentText());
        my_serialport->setcmbBaudRate(ui->cmbBaudRate->currentText());
        my_serialport->setcmbDataBits(ui->cmbDataBits->currentIndex());
        my_serialport->setcmbParity(ui->cmbParity->currentIndex());
        my_serialport->setcmbFlowControl(0);
        my_serialport->setcmbStopBits(ui->cmbStopBits->currentIndex());
        my_serialport->SerialConnect();
            //每秒读一次
            ui->cmbPortName->setEnabled(false);
            ui->cmbBaudRate->setEnabled(false);
            ui->cmbParity->setEnabled(false);
            ui->cmbDataBits->setEnabled(false);
            ui->cmbStopBits->setEnabled(false);
            ui->btnOpen->setText("关闭串口");
            state=true;
            //QMessageBox::about(NULL, "Sign", "Serial is opened!");
        }
    }
    else
    {
        state=false;
        ui->btnOpen->setText("打开串口");
        ui->cmbPortName->setEnabled(true);
        ui->cmbBaudRate->setEnabled(true);
        ui->cmbParity->setEnabled(true);
        ui->cmbDataBits->setEnabled(true);
        ui->cmbStopBits->setEnabled(true);
        my_serialport->mySerialDisconnect();
    }
    timer->start(1000);
}

void Widget::on_btnSend_released()
{
    //获取发送区的数据
    QString sendData = ui->teSendData->toPlainText();
    QByteArray sendData_2 = sendData.toLatin1();
    //写入缓冲区
    my_serialport->write(sendData_2);
}

void Widget::on_clearRecive_released()
{
    ui->teReceiveData->clear();
}

void Widget::on_clearSend_released()
{
    ui->teSendData->clear();
}
void Widget::on_cbReceive_stateChanged(int arg1)
{
    if(ui->cbReceive->isChecked())
    {
        ui->teReceiveData->setVisible(false);
        ui->teReceiveDataHex->setVisible(true);
        receiveStat=false;
    }
    else {

        ui->teReceiveDataHex->setVisible(false);
        ui->teReceiveData->setVisible(true);
        receiveStat=true;
    }
    qDebug()<<receiveStat<<endl;
}

void Widget::on_cbSend_stateChanged(int arg1)
{
    if(ui->cbSend->isChecked())
    {
        ui->teSendData->setVisible(false);
        ui->teSendDataHex->setVisible(true);
        sendStat=false;
    }
    else {
        ui->teSendDataHex->setVisible(false);
        ui->teSendData->setVisible(true);
        sendStat=true;
    }
}

void Widget::on_teReceiveData_textChanged()
{
    if(receiveStat==true)
    {
        QString string1= ui->teReceiveData->toPlainText();
        ui->teReceiveDataHex->clear();
        ui->teReceiveDataHex->setText(ByteArrayToHexString(string1.toUtf8()));
    }
}
QString Widget::deleteCharString0(QString sourceString, char chElemData) {
    QString resultString = "";
    for (int i = 0; i < sourceString.length(); i++) {
        if (sourceString.at(i)!= chElemData) {
            resultString += sourceString.at(i);
        }
    }
    return resultString;
}

void Widget::on_teReceiveDataHex_textChanged()
{
    if(receiveStat==false)
    {
        QString string1= ui->teReceiveDataHex->toPlainText();
        string1=deleteCharString0(string1,' ');
        QString string2="";
        for(int i=0;i<string1.length();i++,i++)
        {
           char *num=new char[2];
           QString num2="";
            if(i<string1.length()-1)
            {
                num[0]=string1.at(i).toLatin1();
                num[1]=string1.at(i+1).toLatin1();
                num2=QString::fromUtf8(num);
            }
            else {
                num[0]='0';
                num[1]=string1.at(i).toLatin1();
                num2=QString::fromUtf8(num);
            }
            char c=(num[0]-0x30)*16+num[1]-0x30;

           string2.append(c);
        }
        ui->teReceiveData->clear();
        ui->teReceiveData->setText(string2);
    }
}

void Widget::on_teSendData_textChanged()
{
    if(sendStat==true)
    {
        QString string1= ui->teSendData->toPlainText();
        ui->teSendDataHex->clear();
        ui->teSendDataHex->setText(ByteArrayToHexString(string1.toUtf8()));
    }
}

void Widget::on_teSendDataHex_textChanged()
{
    if(sendStat==false)
    {
        QString string1= ui->teSendDataHex->toPlainText();
        string1=deleteCharString0(string1,' ');
        QString string2="";
        for(int i=0;i<string1.length();i++,i++)
        {
           char *num=new char[2];
           QString num2="";
            if(i<string1.length()-1)
            {
                num[0]=string1.at(i).toLatin1();
                num[1]=string1.at(i+1).toLatin1();
                num2=QString::fromUtf8(num);
            }
            else {
                num[0]='0';
                num[1]=string1.at(i).toLatin1();
                num2=QString::fromUtf8(num);
            }
            char c=(num[0]-0x30)*16+num[1]-0x30;

           string2.append(c);
        }
        ui->teSendData->clear();
        ui->teSendData->setText(string2);
    }
}

界面展示

左右两边的控件均为QTableView。

Qt 可以做什么?

Qt 虽然经常被当做一个 GUI 库,用来开发图形界面应用程序,但这并不是 Qt 的全部;Qt 除了可以绘制漂亮的界面(包括控件、布局、交互),还包含很多其它功能,比如多线程、访问数据库、图像处理、音频视频处理、网络通信、文件操作等,这些 Qt 都已经内置了。

大部分应用程序都可以使用 Qt 实现,除了与计算机底层结合特别紧密的,例如驱动开发,它直接使用硬件提供的编程接口,而不能使用操作系统自带的函数库。

下面的程序都使用 Qt 开发:WPS、YY语音、Skype、豆瓣电台、虾米音乐、淘宝助理、千牛、暴雪的战网客户端、VirtualBox、Opera、咪咕音乐、Google地图、Adobe Photoshop Album 等。

Linux 也是嵌入式的主力军,广泛应用于消费类电子、工业控制、军工电子、电信/网络/通讯、航空航天、汽车电子、医疗设备、仪器仪表等相关行业。

Qt 虽然也支持手机操作系统,但是由于 Android 本身已经有Java和 Kotlin,iOS 本身已经有 Objective-C 和 Swift,所以 Qt 在移动端的市场份额几乎可以忽略。

总起来说,Qt 主要用于桌面程序开发和嵌入式开发。

 本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值