《Qt开发》Qt 串口通信(VS2013+qt)

一、知识要点

Qt中使用QSerialPort类管理串口通信。

1.参数设置

常用的设置参数有:端口号、波特率、数据位、停止位、校验位、流控制

使用如下方法对各个参数进行设置:

void  setPortName(const QString &name) :设置端口号

bool  setBaudRate(qint32 baudRate, Directions directions = AllDirections) :设置波特率

bool  setDataBits(DataBits dataBits) :设置数据位

bool  setStopBits(StopBits stopBits) :设置停止位

bool  setParity(Parity parity) :设置校验位

bool  setFlowControl(FlowControl flowControl): 设置流控制

串口参数

名称

端口号

portName

自定义,如COM1、COM2

波特率

BaudRate

Baud1200,Baud2400,Baud4800, Baud9600, ..., UnknownBaud

数据位

DataBits

Data5, Data6, Data7, Data8, UnknownDataBits

停止位

StopBits

OneStop, OneAndHalfStop, TwoStop, UnknownStopBits

校验位

Parity

NoParity,EvenParity,OddParity,SpaceParity,MarkParity, UnknownParity

流控制

FlowControl

NoFlowControl,HardwareControl,SoftwareControl, UnknownFlowControl

 2.打开串口

[virtual] bool QSerialPort::open(OpenMode mode),有如下几种打开模式:

Constant

Value

Description

QIODevice::NotOpen

0x0000

The device is not open.

QIODevice::ReadOnly

0x0001

The device is open for reading.

QIODevice::WriteOnly

0x0002

The device is open for writing. Note that this mode implies Truncate.

QIODevice::ReadWrite

ReadOnly | WriteOnly

The device is open for reading and writing.

QIODevice::Append

0x0004

The device is opened in append mode so that all data is written to the end of the file.

QIODevice::Truncate

0x0008

If possible, the device is truncated before it is opened. All earlier contents of the device are lost.

QIODevice::Text

0x0010

When reading, the end-of-line terminators are translated to '\n'. When writing, the end-of-line terminators are translated to the local encoding, for example '\r\n' for Win32.

QIODevice::Unbuffered

0x0020

Any buffer in the device is bypassed.

 3. 通信

当串口中接收到数据时,会发送readyRead()信号,可以编写关联该信号的槽函数,来接收存储数据

接收函数:

[virtual] qint64 QSerialPort::bytesAvailable() const

qint64 QIODevice::read(char *data, qint64 maxSize)

QByteArray QIODevice::read(qint64 maxSize)

QByteArray QIODevice::readAll()

发送函数:

qint64 QIODevice::write(const char *data, qint64 maxSize)

qint64 QIODevice::write(const char *data)

qint64 QIODevice::write(const QByteArray &byteArray)

4. 关闭串口

[virtual] void QSerialPort::close()

二、编程实战

开发环境:VS2013+Qt5.9.3+Virtual Serial Port Device+串口助手

先添加一对虚拟串口,如下图:

《Qt开发》Qt 串口通信(VS2013+qt)_第1张图片

然后使用开发的串口通信软件和串口助手进行通信,运行结果如下图:

《Qt开发》Qt 串口通信(VS2013+qt)_第2张图片

参考代码:

SerialPortDemo.h

添加如下声明:

public:

    //串口部分

    QSerialPort serialPort;

    bool connectFlag;

 

    //数据存储

    QString qexeFullPath;

    QString fileNamePath;

    QFile *file;

 

    QByteArray buffer;           //数据存储缓冲区

    QByteArray recvBytes;        //接收字节数

    QByteArray sendBytes;        //发送字节数

 

    void Init();                 //初始化

    void coSignalSlot();         //关联信号和槽

    void getSerialPort();        //获取串口设置的值

 

    public slots:

    //点击按钮对应的槽函数

    void openSerialPort();       //打开串口  

    void sendMsg();              //发送数据

    void saveData();             //保存数据

 

SerialPortDemo.cpp

SerialPort::SerialPort(QWidget *parent)

: QWidget(parent)

, file(nullptr)

, connectFlag(true)

, recvBytes(0)

, sendBytes(0)

{

    ui.setupUi(this);

    qexeFullPath = QCoreApplication::applicationDirPath() + "/../";

    Init();

    coSignalSlot();

    //设置背景颜色

    this->setStyleSheet(".QWidget{background:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0.3 rgb(153,136,13), stop: 1 rgb(211,187,18));}");//渐变背景

    ui.widget_4->setStyleSheet("QWidget{background:rgb(150,100,0)}");//状态栏

}

SerialPort::~CheckASIC()

{

    //关闭串口

    if (file != NULL && file->isOpen())

    {

        file->close();

        delete file;

        file = NULL;

    }

}

void SerialPort::Init()

{

    //初始化串口设置相关字符串

    QStringList portStr, baudRateStr, dataBitsStr, stopBitsStr, parityStr, flowControlStr, instructStr;

    portStr << "COM1" << "COM2" << "COM3" << "COM4" << "COM5" << "COM6" << "COM7" << "COM8"

        << "COM9" << "COM10" << "COM11" << "COM12" << "COM13" << "COM14" << "COM15" << "COM16";

    baudRateStr << "110" << "300" << "600" << "1200" << "2400" << "4800" << "9600"

        << "14400" << "19200" << "38400" << "56000" << "57600" << "119200";

    dataBitsStr << "5 bit" << "6 bit" << "7 bit" << "8 bit";

    stopBitsStr << "1 bit" << "1.5 bit" << "2 bit";

    parityStr << "NONE" << "EVEN" << "ODD" << "MARK" << "SPACE";

    flowControlStr << "None" << "Hardware" << "Software";

 

    //初始化串口各参数列表

    ui.cbBoxPort->addItems(portStr);

    ui.cbBoxBaudRate->addItems(baudRateStr);

    ui.cbBoxDataBits->addItems(dataBitsStr);

    ui.cbBoxStopBits->addItems(stopBitsStr);

    ui.cbBoxParity->addItems(parityStr);

    ui.cbBoxFlowControl->addItems(flowControlStr);

 

    //设置串口各参数的默认索引

    ui.cbBoxPort->setCurrentIndex(0);

    ui.cbBoxBaudRate->setCurrentIndex(12);

    ui.cbBoxDataBits->setCurrentIndex(3);

    ui.cbBoxStopBits->setCurrentIndex(0);

    ui.cbBoxParity->setCurrentIndex(0);

    ui.cbBoxFlowControl->setCurrentIndex(0);

 

    //打开按钮样式

    ui.pBtnOpenPort->setStyleSheet("QPushButton{background: #770000;color:white}");

}

 

//信号和槽关联

void SerialPort::coSignalSlot()

{

    connect(ui.pBtnOpenPort, SIGNAL(clicked()), this, SLOT(openSerialPort()));

    connect(ui.pBtnSend, SIGNAL(clicked()), this, SLOT(sendMsg()));

}

//获取串口设置值

void SerialPort::getSerialPort()

{

    //设置串口名称

    serialPort.setPortName(ui.cbBoxPort->currentText());

    //设置波特率

    qint32 baudRate = ui.cbBoxBaudRate->currentText().toInt();

    serialPort.setBaudRate(baudRate);

    //设置数据位

    if (ui.cbBoxDataBits->currentIndex() == 3)

    {

        serialPort.setDataBits(QSerialPort::Data8);

    }

    else if (ui.cbBoxDataBits->currentIndex() == 2)

    {

        serialPort.setDataBits(QSerialPort::Data7);

    }

    else if (ui.cbBoxDataBits->currentIndex() == 1)

    {

        serialPort.setDataBits(QSerialPort::Data6);

    }

    else if (ui.cbBoxDataBits->currentIndex() == 0)

    {

        serialPort.setDataBits(QSerialPort::Data5);

    }

    //设置停止位

    if (ui.cbBoxStopBits->currentIndex() == 0)

    {

        serialPort.setStopBits(QSerialPort::OneStop);

    }

    else if (ui.cbBoxStopBits->currentIndex() == 1)

    {

        serialPort.setStopBits(QSerialPort::OneAndHalfStop);

    }

    else if (ui.cbBoxStopBits->currentIndex() == 2)

    {

        serialPort.setStopBits(QSerialPort::TwoStop);

    }

    //设置校验位

    if (ui.cbBoxParity->currentIndex() == 0)

    {

        serialPort.setParity(QSerialPort::NoParity);

    }

    else if (ui.cbBoxParity->currentIndex() == 1)

    {

        serialPort.setParity(QSerialPort::EvenParity);

    }

    else if (ui.cbBoxParity->currentIndex() == 2)

    {

        serialPort.setParity(QSerialPort::OddParity);

    }

    else if (ui.cbBoxParity->currentIndex() == 3)

    {

        serialPort.setParity(QSerialPort::MarkParity);

    }

    else if (ui.cbBoxParity->currentIndex() == 4)

    {

        serialPort.setParity(QSerialPort::SpaceParity);

    }

    //设置是否流控制

    if (ui.cbBoxFlowControl->currentIndex() == 0)

    {

        serialPort.setFlowControl(QSerialPort::NoFlowControl);

    }

    else if (ui.cbBoxFlowControl->currentIndex() == 1)

    {

        serialPort.setFlowControl(QSerialPort::HardwareControl);

    }

    else if (ui.cbBoxFlowControl->currentIndex() == 2)

    {

        serialPort.setFlowControl(QSerialPort::SoftwareControl);

    }

}

//打开串口

void SerialPort::openSerialPort()

{

    getSerialPort();

    //connectFlag默认为true,然后直接执行if中的语句,打开串口

    if (connectFlag)

    {

        serialPort.open(QIODevice::ReadWrite);

        //初始化相关变量

        connectFlag = !connectFlag;

        recvBytes = 0;

        sendBytes = 0;

 

        ui.pBtnOpenPort->setText("关闭串口");                                //打开串口时显示关闭串口字样

        ui.pBtnOpenPort->setStyleSheet("QPushButton{background: #FF0000;}"); //串口打开后,按钮变为红色

        ui.widget_4->setStyleSheet("QWidget{background:rgb(0,152,0);}");     //串口打开后,状态栏变为绿色

     

       if (file == NULL//如果文件不存在,创建新文件,每次打开串口都创建新文件                   

        {

             QDateTime currentTime = QDateTime::currentDateTime();               //获取系统现在的时间

             QString fileName = "Data_" + currentTime.toString("yyyyMMddhhmmss") + ".dat"; //以打开串口的时间命名文件

             fileNamePath = qexeFullPath + "SaveData/" + fileName;

             ui.labelSavePath->setText("存储路径:" + fileNamePath);

             file = new QFile(fileNamePath);

             if (!file->open(QIODevice::WriteOnly))

             {

                 return;

             }

        }

        connect(&serialPort, SIGNAL(readyRead()), this, SLOT(saveData()));//串口有数据时发射readyRead()信号

    }

    else

    {

        serialPort.close();

        connectFlag = !connectFlag;

        //关闭串口

        if (file != NULL)

        {

            delete file;

             file = NULL;

        }

        ui.pBtnOpenPort->setText("打开串口");

        ui.pBtnOpenPort->setStyleSheet("QPushButton{background: #770000;color:white;}");

       ui.widget_4->setStyleSheet("QWidget{background:rgb(7,152,214);}");//状态栏

    }

}

//=================================数据存储部分======================================

//接收存储数据

void SerialPort::saveData()

{

    if (serialPort.isOpen())

    {

        buffer = serialPort.readAll();//读取数据到缓冲数组中

        recvBytes += buffer;

        qulonglong rcvBytesLen = recvBytes.size();

        ui.labelRecv->setText("    Recv:" + QString::number(rcvBytesLen));

 

        if (buffer.size() > 0)

        {

             ui.plainTextEdit->appendPlainText(QString(buffer));

             if (file->isOpen())

             {

                 file->write(buffer);

                 file->close();

             }

             else

             {

                 if (!file->open(QIODevice::WriteOnly | QIODevice::Append))

                 {

                     return;

                 }

                 file->write(buffer);

                 file->close();

             }

        }

    }

}

//指令发送

void SerialPort::sendMsg()

{

    if (serialPort.isOpen())

    {

        QString msg = ui.plainTextEdit_2->toPlainText();

        serialPort.write(msg.toUtf8());//字符串转QByteArray,将数据发送到串口

        QByteArray sendByte = msg.toUtf8();

        sendBytes += sendByte;

        qulonglong sendBytesLen = sendBytes.size();

        ui.labelSend->setText("    Send:" + QString::number(sendBytesLen));

    }

}

 

你可能感兴趣的:(Qt,串口通信,qt5)