赞
踩
QT学了一点发现学不进去,索性看看能不能直接撸个程序,于是就有了这个简易的串口软件…
这是XCOM串口收发软件,以此为例
目的很明确:
- 串口列表要能显示所有已经接上PC上的COM
- 以我们的配置115200-8-1-N打开串口
- 能收、发
既然用到串口,那么我们就要在.pro里增加串口的库
QT += serialport # 串口库
以及mainwindow.h里添加头文件
#include "qDebug.h" // 调试输出用
#include <QtSerialPort/QSerialPort> // 提供访问串口的功能
#include <QtSerialPort/QSerialPortInfo> // 提供系统中存在的串口的信息
要注意的是,除了Label,其他的控件都记得命名呀,当然你用默认的也行…
我们要打开的串口,并不希望他是临时变量,我们用到的地方多呢!所以就在头文件先定义一个私有成员变量
QSerialPort *serial;
我们希望他在打开的时候就能加载所有的COM,所以我们在MainWindow里做这一步,创建窗口的时候就初始化COM列表,顺带着我们为serial开辟空间
// 我们在 ui->setupUi(this); 后面加入这些代码即可
// 添加所有串口到comboBox里(串口号的名字叫comboBox_COMx)
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->comboBox_COMx->addItem(info.portName()); //+':'+info.description()
}
serial = new QSerialPort(this);
我们用info去引用一个个的从串口的列表里取出COM的信息,如果有,我们就把他加入到【串口选择】的下拉栏里
这个时候如果我们运行,就会发现【串口选择】里已有了PC上已插入的COM设备。
首先为按钮【打开串口】添加槽,然后在槽函数里编写我们的代码:
打开了 总不能就一直开吧,所以我们做了一个开关,通过按钮上的字来判断是开还是关
// 点击打开串口
if(ui->pushButton_OpenSerial->text()==tr("打开串口"))
{
ui->pushButton_OpenSerial->setText(tr("关闭串口"));
}
else
{
ui->pushButton_OpenSerial->setText(tr("打开串口"));
}
这个时候我们运行,会发现打开串口的按钮已经可以正常工作了,点击打开,会显示关闭按钮。点击关闭,会显示打开按钮。
按钮做完了,接着就要做功能了,如果要关闭,我们就可以调用serial->close();来关闭串口,如果要打开,我们就去打开,不过不知道能不能打开(可能别的程序正在使用),所以加个if判断一下。
// 点击打开串口 if(ui->pushButton_OpenSerial->text()==tr("打开串口")) { ui->pushButton_OpenSerial->setText(tr("关闭串口")); // 设置串口号(以当前显示的COM号为要打开的串口) serial->setPortName(ui->comboBox_COMx->currentText()); // 以读写方式打开串口 if(serial->open(QIODevice::ReadWrite)) { qDebug() << "Open OK" << endl; } else { qDebug() << "Open Failed" << endl; } } else { ui->pushButton_OpenSerial->setText(tr("打开串口")); serial->close(); }
现在我们运行一下,看调试信息知道目前都是正确的。能正确开关串口。
既然打开了串口,那么我们就配置一下串口的参数,因为只是一个简易的,所以就固定死串口为8-1-N,把一下代码放入成功打开串口的if内。
//设置波特率
serial->setBaudRate(115200);
//设置数据位
serial->setDataBits(QSerialPort::Data8);
//设置校验位
serial->setParity(QSerialPort::NoParity);
//设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);
//设置停止位
serial->setStopBits(QSerialPort::OneStop);
这就完了吗?还没有,我们配置好了串口,如何进行接收呢?我们利用的是QT的信号与槽机制,当串口收到数据,就会发出readyRead()信号,所以我们利用这个信号,建立一个槽用来接收字符。
先在头文件定义private slots函数 void recv_data(void);
然后我们紧接着刚刚配置串口后面写上connect()来连接信号与槽
connect(serial, SIGNAL(readyRead()), this, SLOT(recv_data()));
这样我们点击打开信号与槽后,就会配置串口,激活信号与槽。
现在万事俱备,只欠东风,我们继续写槽函数recv_data()来接收串口的数据
仔细思考一下,平时在用串口软件的时候,有新的数据发来会自动出现在旧的数据后面。
所以我们的做法是,先暂时保存显示的数据,然后把读到的数据加在后面,再清除显示的数据,把合成的数据再显示出来,就达到我们的效果了。
void MainWindow::recv_data(void)
{
qDebug() << "Recv Data" << endl;
QByteArray buf = serial->readAll();
if(!buf.isEmpty())
{
QString str = ui->textEdit_ReceiveMsg->toPlainText();
str+=tr(buf);
ui->textEdit_ReceiveMsg->clear();
ui->textEdit_ReceiveMsg->append(str);
}
}
这个时候我们运行一下,打开串口,用单片机来发数据,实测已经可以正确显示在屏幕上了
对于发送数据,有了刚才的经验就比较简单了。
为UI的【发送】键添加一个槽函数,当我们点击【发送】时,串口就发送我们写入的信息。
所以我们在发送的槽函数内写入:
// 先读取我们写入的文本
QString str = ui->textEdit_SendMsg->toPlainText().toLatin1();
qDebug() << str <<endl;
// 写入
serial->write(str.toLatin1());
串口的write函数的参数有两个
- 第一个是char *类型,所以我们要str转char *,用的.toLatin1()来转换。
- 第二个是传入字符最大数量(我选择不设置所以没填)
此时我们再运行,发现收发都正常了。
附上我的完整代码(不包含UI,看控件的英文名字应该能对上图片)
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QtSerialPort/QSerialPort> // 提供访问串口的功能 #include <QtSerialPort/QSerialPortInfo> // 提供系统中存在的串口的信息 namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_pushButton_OpenSerial_clicked(); void recv_data(void); void on_pushButton_SendMsg_clicked(); void on_pushButton_ClearRecv_clicked(); private: Ui::MainWindow *ui; QSerialPort *serial; }; #endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "qDebug.h" #include "QObject" #include "QTimer" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化 // 添加所有串口到comboBox里(串口号的名字叫comboBox_COMx) foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { ui->comboBox_COMx->addItem(info.portName()); //+':'+info.description() } serial = new QSerialPort(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::recv_data(void) { qDebug() << "Recv Data" << endl; QByteArray buf = serial->readAll(); if(!buf.isEmpty()) { QString str = ui->textEdit_ReceiveMsg->toPlainText(); str+=tr(buf); ui->textEdit_ReceiveMsg->clear(); ui->textEdit_ReceiveMsg->append(str); } } void MainWindow::on_pushButton_OpenSerial_clicked() { // 点击打开串口 if(ui->pushButton_OpenSerial->text()==tr("打开串口")) { ui->pushButton_OpenSerial->setText(tr("关闭串口")); // 开辟空间 //serial = new QSerialPort(this); // 设置串口号 serial->setPortName(ui->comboBox_COMx->currentText()); // 以读写方式打开串口 if(serial->open(QIODevice::ReadWrite)) { qDebug() << "Open OK" << endl; // 此处写死为 8-1-N //设置波特率 serial->setBaudRate(115200); //设置数据位 serial->setDataBits(QSerialPort::Data8); //设置校验位 serial->setParity(QSerialPort::NoParity); //设置流控制 serial->setFlowControl(QSerialPort::NoFlowControl); //设置停止位 serial->setStopBits(QSerialPort::OneStop); connect(serial, SIGNAL(readyRead()), this, SLOT(recv_data())); } else { qDebug() << "Open Failed" << endl; } } else { ui->pushButton_OpenSerial->setText(tr("打开串口")); serial->close(); } } void MainWindow::on_pushButton_SendMsg_clicked() { QString str = ui->textEdit_SendMsg->toPlainText().toLatin1(); qDebug() << str <<endl; serial->write(str.toLatin1()); } void MainWindow::on_pushButton_ClearRecv_clicked() { ui->textEdit_ReceiveMsg->clear(); }
其实还有很多其他的功能可以加进去,我就多做了一个【清除接收】…
甚至还有BUG…就是只有打开软件的时候才加载已有COM口,所以还要加上点击下拉框的时候就扫描更新一遍。
此时的波特率、停止位啥的都是写死的,所以真正要做完的话,还需要把这些控件都做上
还有等等等等…
哈哈 主要功能做出来了,其他的往上添加就好了。
打包exe教程 https://blog.csdn.net/syzdev/article/details/80860619
over…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。