前言
前几天使用stm32时经常使用到串口调试助手来调试程序,然后今天就想着自己能不能也写一个串口调试助手。然后就开始找资料。最后写出一个串口调试助手。结果使用在stm32上时发现会终止我的stm32上运行的程序,但是在51单片机上却可以运行成功。(具体原因我也不清楚)
一、开发环境
- Qt creator
- 辅助环境:89C51上跑串口程序(主机发送数据给单片机,单片机返回数据给主机的程序)。
二、串口调试助手组成
- .pro文件 在QT += core gui后面加上serialport
代码如下(示例):
QT += core gui serialport
- .ui文件
3. 串口读取数据
当串口有数据接收时会触发readyRead()信号
connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData); //读取数据
- 往串口写数据
serial->write(msg.toUtf8());
三、各文件代码
mainwindow.h代码如下(示例):
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSerialPort>
#include <QSerialPortInfo>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void serialInit(); //串口初始化程序
private slots:
void on_pushButton_clicked();
void on_ButtonClear_clicked();
void on_ButtonSend_clicked();
void readData();
private:
Ui::MainWindow *ui;
QSerialPort * serial; //串口对象
char serialFlag = 0; //串口状态:0为关闭,1为打开
QSerialPortInfo serialInfo[5];//定义串口信息数组存放可使用的串口
};
#endif // MAINWINDOW_H
mainwindow.cpp代码如下(示例):
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
serial = new QSerialPort(this);
serialInit(); //串口的初始化
connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData); //读取数据
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
if(0 == serialFlag)
{
for(int i=0; i<5; i++)
{
if(serialInfo[i].portName() == ui->BoxPort->currentText()) //更新选中的串口
{
serial->setPort(serialInfo[i]);
}
}
if(serial->open(QIODevice::ReadWrite)) //开启串口
{
serialFlag = 1;
ui->labelState->setText("打开"); //label显示串口状态
serial->setPortName(ui->BoxPort->currentText()); //设置端口名
serial->setBaudRate(ui->BoxBaudRate->currentText().toInt()); //设置波特率
serial->setDataBits(QSerialPort::Data8); //设置8个数据位
serial->setParity(QSerialPort::NoParity); //设置无校验位
serial->setStopBits(QSerialPort::OneStop); //设置停止位
serial->setFlowControl(QSerialPort::NoFlowControl); //设置无流控制
}
}
else if(1 == serialFlag)
{
serial->close();
serialFlag = 0;
ui->labelState->setText("关闭");
}
}
void MainWindow::on_ButtonClear_clicked()
{
ui->textReceive->clear(); //清空文本内容
}
void MainWindow::on_ButtonSend_clicked()
{
QString msg = ui->textSend->toPlainText(); //获取文本输入框的内容
serial->write(msg.toUtf8()); //转成字节数组发送
}
void MainWindow::readData()
{
QByteArray buf;
buf = serial->readAll(); //读取串口数据
ui->textReceive->append(tr(buf)); //追加串口内容
}
void MainWindow::serialInit()
{
int i = 0;
//类似for循环查找本机的可使用的串口
foreach(const QSerialPortInfo & info, QSerialPortInfo::availablePorts())
{
qDebug() << "portName:" << info.portName();
qDebug() << "Description:" << info.description();
serialInfo[i] = info; //定义5个串口信息数组保存各个串口的信息
serial->setPort(info); //绑定串口
if(serial->open(QIODevice::ReadWrite)) //第一次打开串口,看看串口能不能正常打开
{
ui->BoxPort->addItem(info.portName());
serial->close(); //初始化后默认串口关闭的
}
i++;
}
QStringList baudList;
QStringList parityList;
QStringList dataBitsList;
QStringList stopBitsList;
baudList << "4800" << "9600" << "19200" << "115200" << "128000" << "256000"; //设置波特率
ui->BoxBaudRate->addItems(baudList);
ui->BoxBaudRate->setCurrentIndex(0);
parityList << "No"; //设置奇偶校验位
ui->BoxParity->addItems(parityList);
ui->BoxParity->setCurrentIndex(0);
dataBitsList << "8"; //设置数据位
ui->BoxDataBit->addItems(dataBitsList);
ui->BoxDataBit->setCurrentIndex(0);
stopBitsList << "1"; //设置停止位
ui->BoxStopBit->addItems(stopBitsList);
ui->BoxStopBit->setCurrentIndex(0);
}
main.cpp代码如下(示例):
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle("串口调试助手");
w.show();
return a.exec();
}
四、实验结果
首先端口选中51单片机的端口,这里我设置的波特率是4800,当我们在信息发送窗口输入文字,点击发送信息按钮,51单片机收到信息返回给电脑,电脑再出现显示再信息接收窗口。
总结
提示:这里面有些代码写的不是很好。而且使用stm32调试也有bug。如果大家有更好的写法,欢迎和我一起交流。
最后记录一下编写中遇到的错误:QIODevice::write: device not open;
解决办法:
- 检查硬件连接是否出现问题
- 检查代码中的逻辑,例如 serial->open(QIODevice::ReadWrite) 打开成功会返回true,所以编写时使用if(serial->open(QIODevice::ReadWrite))逻辑来控制。更加容易发现问题。