<QT学习>QT中串口QSerialport类学习与使用
QT5中已经增加了串口类QSrialPort,可以直接调用API函数进行快速开发。
注意qmake那边:QT += serialport。要把QT += serialport在加到.pro文件中
1. 获取串口信息
Dialog::Dialog(QWidget *parent) : QDialog(parent) { const auto infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &info : infos) serialPortComboBox->addItem(info.portName()); }
- QSerialPortInfo::availablePorts()
函数的功能时会检测当前电脑上串行端口,并且返回系统上串行端口的信息。
之后将获取到的信息加入Qcombobox下拉选项框中。本例中只添加了串口的名字即COM4。
2.设置串口参数并开启串口
void Dialog::openSerial() { if(runButton->text() == tr("开启")) { serial = new QSerialPort(); //port name serial->setPortName(serialPortComboBox->currentText()); //open serial->open(QIODevice::ReadWrite); serial->setBaudRate(115200); serial->setDataBits(QSerialPort::Data8); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl);
/* 一定要写,不然串口接收不到数据 */ connect(serial, SIGNAL(readyRead()), this, SLOT(readParam())); runButton->setText("关闭"); } else { serial->clear(); serial->close(); serial->deleteLater(); runButton->setText("开启"); } }connect(serial, SIGNAL(readyRead()), this, SLOT(readParam()));
该函数是启动串口接收功能。即当串口有数据时,readyRead()信号就会被抛出。对应的readParam()即QT中所定义的槽就会被调用。
注意:
readyRead()信号是有数据就直接抛出,在实际数据交互中,往往一帧数据有很多字节。这意味着我们一帧数据数据会触发多次信号。应当在对数据进行操作时候对数据进行校验。
3.串口发送数据
serial->write(sendData);
sendData为QByteArray类所创建的对象,即数据缓存区。
4.串口接收数据
g_RecBuf.append(serial->readAll());
readAll函数会读取当前设备所有剩余数据,并将它作为字节数组返回。
以上实例源码:
dialog.cpp
#include "dialog.h" #include <QDebug> #include <QThread> #include <QTimer> Dialog::Dialog(QWidget *parent) : QDialog(parent) { serialPortComboBox = new QComboBox(); readParaBox = new QComboBox(); writeParaBox = new QComboBox(); runButton = new QPushButton(tr("开启")); readPara = new QPushButton(tr("读取参数")); writePara = new QPushButton(tr("下发参数")); onlyOneRead = new QPushButton(tr("一键读取")); onlyOneWrite = new QPushButton(tr("一键下发")); cmd = readFlag; timer = new QTimer(); /* add comprot into combobox item */ const auto infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &info : infos) serialPortComboBox->addItem(info.portName()); readParaBox->addItem(tr("读取参数地址1")); readParaBox->addItem(tr("读取参数地址2")); readParaBox->addItem(tr("读取参数地址3")); readParaBox->addItem(tr("读取参数地址4")); readParaBox->addItem(tr("读取参数地址5")); writeParaBox->addItem(tr("下发参数地址1")); writeParaBox->addItem(tr("下发参数地址2")); writeParaBox->addItem(tr("下发参数地址3")); writeParaBox->addItem(tr("下发参数地址4")); writeParaBox->addItem(tr("下发参数地址5")); auto mainLayout = new QGridLayout; mainLayout->addWidget(serialPortComboBox, 0, 0); mainLayout->addWidget(runButton, 0, 1); mainLayout->addWidget(readParaBox,1,0); mainLayout->addWidget(readPara, 1, 1); mainLayout->addWidget(writeParaBox,2,0); mainLayout->addWidget(writePara, 2, 1); mainLayout->addWidget(onlyOneRead,3,0); mainLayout->addWidget(onlyOneWrite,3,1); setLayout(mainLayout); connect(runButton, &QPushButton::clicked, this, &Dialog::openSerial); connect(readPara, &QPushButton::clicked, this, &Dialog::sendCmd); connect(writePara, &QPushButton::clicked, this, &Dialog::writeParam); connect(timer, SIGNAL(timeout()), this, SLOT(timerStop())); connect(onlyOneRead,&QPushButton::clicked,this,&Dialog::oneRead); connect(onlyOneWrite,&QPushButton::clicked,this,&Dialog::oneWrite); } void Dialog::openSerial() { if(runButton->text() == tr("开启")) { serial = new QSerialPort(); //port name serial->setPortName(serialPortComboBox->currentText()); //open serial->open(QIODevice::ReadWrite); serial->setBaudRate(115200); serial->setDataBits(QSerialPort::Data8); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); connect(serial, SIGNAL(readyRead()), this, SLOT(readParam())); runButton->setText("关闭"); } else { serial->clear(); serial->close(); serial->deleteLater(); runButton->setText("开启"); } } void Dialog::writeParam(void) { QByteArray sendData; sendData.resize(1026); QString strWriteFile = writeParaBox->currentText(); strWriteFile.append(".dat"); if(strWriteFile == "下发参数地址1.dat") { file.setFileName("读取参数地址1.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } } else if(strWriteFile == "下发参数地址2.dat") { file.setFileName("读取参数地址2.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } } else if(strWriteFile == "下发参数地址3.dat") { file.setFileName("读取参数地址3.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } } else if(strWriteFile == "下发参数地址4.dat") { file.setFileName("读取参数地址4.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } } else if(strWriteFile == "下发参数地址5.dat") { file.setFileName("读取参数地址5.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } } file.close(); sendData.clear(); } void Dialog::timerStop(void) { g_RecBuf.prepend(0xBB); timer->stop(); { QByteArray leftAck = g_RecBuf.left(2); QByteArray rightAck = g_RecBuf.right(1); QByteArray byte1; QByteArray byte2; byte1.append(0xBB); byte1.append(0xAA); byte2.append(0xFF); if(g_RecBuf.size() > 30) { Dialog::saveDataToFile(g_RecBuf); } else if(leftAck == byte1 && rightAck == byte2 && cmd == writeFlag) { cmd = readFlag; msglabel = new QLabel(); QMessageBox::question(this,tr("提示"),tr("下发参数成功"), QMessageBox::Ok); } } g_RecBuf.clear(); } void Dialog::readParam() { timer->start(100); g_RecBuf.append(serial->readAll()); } /* Function: Dialog::saveDataToFile * Describe: Save the data from serial into File */ void Dialog::saveDataToFile(QByteArray &data) { if(cmd == readFlag) { QString strFileName = readParaBox->currentText(); file.setFileName(strFileName.append(".dat")); if(file.open(QFile::WriteOnly)) { file.write(data); } file.close(); } if(cmd != readFlag) { switch (cmd) { case cmd1: file.setFileName("读取参数地址1.dat"); if(file.open(QFile::WriteOnly)) { file.write(data); } file.close(); Dialog::oneRead(); break; case cmd2: file.setFileName("读取参数地址2.dat"); if(file.open(QFile::WriteOnly)) { file.write(data); } file.close(); Dialog::oneRead(); break; case cmd3: file.setFileName("读取参数地址3.dat"); if(file.open(QFile::WriteOnly)) { file.write(data); } file.close(); Dialog::oneRead(); break; case cmd4: file.setFileName("读取参数地址4.dat"); if(file.open(QFile::WriteOnly)) { file.write(data); } file.close(); Dialog::oneRead(); break; case cmd5: file.setFileName("读取参数地址5.dat"); if(file.open(QFile::WriteOnly)) { file.write(data); } file.close(); cmd = readFlag; break; default: break; } } } void Dialog::sendCmd(void) { QByteArray sendpara; unsigned char zero = 0x00; if(readParaBox->currentText() == tr("读取参数地址1")) { sendpara.append(0xAA); sendpara.append(0x33); sendpara.append(0x01); sendpara.append(zero); sendpara.append(zero); sendpara.append(zero); sendpara.append(0xFF); } else if(readParaBox->currentText() == tr("读取参数地址2")) { sendpara.append(0xAA); sendpara.append(0x33); sendpara.append(0x02); sendpara.append(zero); sendpara.append(zero); sendpara.append(zero); sendpara.append(0xFF); } else if(readParaBox->currentText() == tr("读取参数地址3")) { sendpara.append(0xAA); sendpara.append(0x33); sendpara.append(0x03); sendpara.append(zero); sendpara.append(zero); sendpara.append(zero); sendpara.append(0xFF); } else if(readParaBox->currentText() == tr("读取参数地址4")) { sendpara.append(0xAA); sendpara.append(0x33); sendpara.append(0x04); sendpara.append(zero); sendpara.append(zero); sendpara.append(zero); sendpara.append(0xFF); } else if(readParaBox->currentText() == tr("读取参数地址5")) { sendpara.append(0xAA); sendpara.append(0x33); sendpara.append(0x05); sendpara.append(zero); sendpara.append(zero); sendpara.append(zero); sendpara.append(0xFF); } serial->write(sendpara); sendpara.clear(); } void Dialog::oneRead(void) { QByteArray cmdArray; unsigned char zero = 0x00; switch (cmd) { case readFlag: cmdArray.append(0xAA); cmdArray.append(0x33); cmdArray.append(0x01); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(0xFF); cmd = cmd1; serial->write(cmdArray); cmdArray.clear(); break; case cmd1: cmdArray.append(0xAA); cmdArray.append(0x33); cmdArray.append(0x02); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(0xFF); cmd = cmd2; serial->write(cmdArray); cmdArray.clear(); break; case cmd2: cmdArray.append(0xAA); cmdArray.append(0x33); cmdArray.append(0x03); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(0xFF); cmd = cmd3; serial->write(cmdArray); cmdArray.clear(); break; case cmd3: cmdArray.append(0xAA); cmdArray.append(0x33); cmdArray.append(0x04); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(0xFF); cmd = cmd4; serial->write(cmdArray); cmdArray.clear(); break; case cmd4: cmdArray.append(0xAA); cmdArray.append(0x33); cmdArray.append(0x05); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(zero); cmdArray.append(0xFF); cmd = cmd5; serial->write(cmdArray); cmdArray.clear(); break; } } void Dialog::oneWrite(void) { QByteArray sendData; sendData.resize(1026); file.setFileName("读取参数地址1.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } file.close(); sendData.clear(); file.setFileName("读取参数地址2.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } file.close(); sendData.clear(); file.setFileName("读取参数地址3.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } file.close(); sendData.clear(); file.setFileName("读取参数地址4.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } file.close(); sendData.clear(); #if 0 file.setFileName("读取参数地址5.dat"); if(file.open(QFile::ReadOnly)) { sendData = file.readAll(); serial->write(sendData); } file.close(); sendData.clear(); #endif cmd = writeFlag; } Dialog::~Dialog() { }
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QComboBox> #include <QLabel> #include <QPushButton> #include <QGridLayout> #include <QtSerialPort/QSerialPortInfo> #include <QtSerialPort> #include <QFile> #include <QTextStream> #include <QDateTime> #include <QTimer> #include <QMessageBox> enum enumType { readFlag, cmd1, cmd2, cmd3, cmd4, cmd5, writeFlag }; class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private slots: void openSerial(void); void writeParam(void); void sendCmd(void); void timerStop(void); void readParam(void); void oneRead(void); void oneWrite(void); private: void saveDataToFile(QByteArray &data); private: QComboBox *serialPortComboBox; QComboBox *readParaBox; QComboBox *writeParaBox; QPushButton *runButton; QPushButton *readPara; QPushButton *writePara; QPushButton *onlyOneRead; QPushButton *onlyOneWrite; QLabel *msglabel; QSerialPort *serial; QTimer *timer; QFile file; QByteArray g_RecBuf; unsigned int Flag; enumType cmd; }; #endif // DIALOG_H
运行效果:
作用就是通过串口发送以及接收一些数据。