目录
前言
串口通信最重要的点就是所用到的端口,数据位数,波特率,校验位以及停止位。关于理论知识就不解释,直接给代码。
一、环境配置
因为没有实物进行实验,我们可以下载虚拟串口来模拟。
这就相当于多出了COM1和COM2两根线,然后用串口调试助手和QT分别连接其中一个就可以实现串口通信了
二、QT代码编写
UI设计如下
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
SerialPortInit();
}
Widget::~Widget()
{
delete ui;
}
void Widget::SerialPortInit()
{
serial = new QSerialPort;
// 获取计算机中有效的端口号,然后将端口号的名称给端口选择控件
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
serial->setPort(info); // 在对象中设置串口
if(serial->open(QIODevice::ReadWrite)) // 以读写方式打开串口
{
ui->serialComboBox->addItem(info.portName()); // 添加计算机中的端口
serial->close(); // 关闭
} else
{
qDebug() << "串口打开失败,请重试";
}
}
// 参数配置
// 波特率,波特率默认选择115200 ,禁止用户点击
ui->baudComboBox->addItem("115200");
serial->setBaudRate(QSerialPort::Baud115200);
ui->baudComboBox->setDisabled(true);
// 校验,校验默认选择无
ui->crcComboBox->addItem("无");
serial->setParity(QSerialPort::NoParity);
// 数据位,数据位默认选择8位
ui->dataComboBox->addItem("8");
serial->setDataBits(QSerialPort::Data8);
// 停止位,停止位默认选择1位
ui->stopComboBox->addItem("1");
serial->setStopBits(QSerialPort::OneStop);
// 控制流,默认选择无
ui->controlComboBox->addItem("无");
serial->setFlowControl(QSerialPort::NoFlowControl);
// 刷新串口
RefreshSerialPort(0);
// 信号
connect(serial,&QSerialPort::readyRead,this,&Widget::DataReceived); // 接收数据
connect(ui->sendPushButton,&QPushButton::clicked,this,&Widget::DataSend); // 发送数据
}
// 刷新串口
void Widget::RefreshSerialPort(int index)
{
QStringList portNameList; // 存储所有串口名
if(index != 0)
{
serial->setPortName(ui->serialComboBox->currentText()); //设置串口号
}
else
{
ui->serialComboBox->clear(); //关闭串口号
ui->serialComboBox->addItem("刷新"); //添加刷新
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) //添加新串口
{
portNameList.append(info.portName());
}
ui->serialComboBox->addItems(portNameList);
ui->serialComboBox->setCurrentIndex(1); // 当前串口号为COM1
serial->setPortName(ui->serialComboBox->currentText()); //设置串口号
}
}
// 接收数据,使用read () / readLine () / readAll ()
void Widget::DataReceived()
{
char BUF[512] = {0}; // 存储转换类型后的数据
QByteArray data = serial->readAll(); // 读取数据
if(!data.isEmpty()) // 接收到数据
{
QString str = ui->recvTextEdit->toPlainText(); // 返回纯文本
str += tr(data); // 数据是一行一行传送的,要保存所有数据
ui->recvTextEdit->clear(); // 清空之前的数据
ui->recvTextEdit->append(str); // 将数据放入控件中
qDebug() << "str info: " << ui->recvTextEdit->toPlainText();
// 清除之前的数据,防止追加,因为每次获取的数据不一样
int index = str.indexOf("\r\n"); // 找到,返回索引值,找不到,返回-1
if(index != -1)
{
snprintf(BUF,500,"%s", str.left(index + 2).toUtf8().data()); // QString转为char * 类型
qDebug() << "BUF info: " << BUF; // 数据类型转换成功
str.remove(0,index + 2);
// 处理获取到的数据,将其放入对应的控件中
// .....
}
}
}
// 发送数据,write ()
void Widget::DataSend()
{
serial->write(ui->sendTextEdit->toPlainText().toLatin1()); // 串口发送数据
}
void Widget::on_openPushButton_clicked()
{
if(serial->isOpen()) // 如果串口打开了,先给他关闭
{
serial->clear();
serial->close();
// 关闭状态,按钮显示“打开串口”
ui->openPushButton->setText("打开串口");
// 关闭状态,允许用户操作
ui->baudComboBox->setDisabled(false);
ui->crcComboBox->setDisabled(false);
ui->dataComboBox->setDisabled(false);
ui->stopComboBox->setDisabled(false);
ui->controlComboBox->setDisabled(false);
// 禁止操作“发送字符操作”
// ui->SendWordOrder->setDisabled(true);
ui->sendPushButton->setDisabled(true);
ui->status_Label->setText("未连接");
// 清空数据
ui->recvTextEdit->clear();
ui->sendTextEdit->clear();
}
else // 如果串口关闭了,先给他打开
{
//当前选择的串口名字
serial->setPortName(ui->serialComboBox->currentText());
//用ReadWrite 的模式尝试打开串口,无法收发数据时,发出警告
if(!serial->open(QIODevice::ReadWrite))
{
QMessageBox::warning(this,tr("提示"),tr("串口打开失败!"),QMessageBox::Ok);
return;
}
// 打开状态,按钮显示“关闭串口”
ui->openPushButton->setText("关闭串口");
// 打开状态,禁止用户操作
ui->baudComboBox->setDisabled(true);
ui->crcComboBox->setDisabled(true);
ui->dataComboBox->setDisabled(true);
ui->stopComboBox->setDisabled(true);
ui->controlComboBox->setDisabled(true);
// 允许操作“发送字符操作”
// ui->SendWordOrder->setDisabled(false);
ui->sendPushButton->setDisabled(false);
ui->status_Label->setText("已连接");
}
}
//清除接收框中的内容
void Widget::on_clearRecvPushButton_clicked()
{
ui->recvTextEdit->clear();
}
//清除发送框中的内容
void Widget::on_clearSendPushButton_clicked()
{
ui->sendTextEdit->clear();
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
// 引入串口通信的两个头文件(第一步)
#include <QtSerialPort/QSerialPort> // 提供访问串口的功能
#include <QtSerialPort/QSerialPortInfo> // 提供系统中存在的串口信息
#include <QStringList>
#include <QDebug>
#include <QMessageBox>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
void SerialPortInit();
void RefreshSerialPort(int index);
private slots:
void DataReceived();
void DataSend();
private slots:
void on_openPushButton_clicked();
void on_clearRecvPushButton_clicked();
void on_clearSendPushButton_clicked();
private:
Ui::Widget *ui;
QSerialPort *serial;
// 参数配置
QStringList baudList; //波特率
QStringList parityList; //校验位
QStringList dataBitsList; //数据位
QStringList stopBitsList; //停止位
QStringList flowControlList; //控制流
};
#endif // WIDGET_H
三、实验现象
总结
只是简单的实现了串口之间的通信,像设置波特率、选择串口、中文显示、HEX显示等都没有实现,有兴趣可以自己查阅资料进行设计。
链接:https://pan.baidu.com/s/1EJsu8QuWWI1VAqoIAnxD2A?pwd=zxn6
提取码:zxn6