1、前言
串口的基本概念
串口(Serial Port)是计算机与外部设备进行串行通信的接口,通过逐位传输数据实现通信。常见的串口标准包括RS-232、RS-422和RS-485。
串口的工作原理
串口通信通过发送和接收数据线(TX/RX)逐位传输数据。数据以帧为单位,包含起始位、数据位、校验位和停止位。波特率(Baud Rate)决定传输速度,常见值有9600、115200等。
串口的硬件接口
- DB9接口:9针连接器,常见于RS-232标准。
- TTL电平:部分设备使用3.3V或5V电平,需通过电平转换芯片(如MAX232)与RS-232兼容。
串口的软件配置
在操作系统中配置串口需设置以下参数:
- 波特率
- 数据位(通常为8位)
- 校验位(无、奇、偶校验)
- 停止位(1或2位)
串口的应用场景
- 工业控制设备(PLC、传感器)
- 嵌入式系统调试(如单片机通信)
- 老式外设(调制解调器、打印机)
串口调试工具
- Windows:PuTTY、Tera Term
- Linux:minicom、screen命令
现代替代方案
USB转串口模块(如FTDI芯片)和无线串口(蓝牙/Wi-Fi)逐渐取代传统串口,但串口仍广泛用于低成本和可靠通信场景。
2、开始干
1、虚拟串口驱动简介
Virtual Serial Port Driver(VSPD)是一款用于创建虚拟串口对的软件,广泛应用于串口通信测试、开发及模拟场景。它能在计算机上生成虚拟的COM端口,并模拟物理串口的通信行为,无需硬件支持。
主要功能
-
创建虚拟串口对:成对生成虚拟COM端口(如COM1↔COM2),数据可在端口间实时传输。
-
模拟硬件行为:支持波特率、数据位、校验位等参数配置,兼容大多数串口应用程序。
-
跨平台支持:部分版本支持通过网络共享虚拟串口,实现远程通信测试。
典型应用场景
-
软件开发测试:调试串口通信程序时,避免依赖物理设备。
-
硬件模拟:模拟传感器、PLC等设备的串口数据交互。
-
教学演示:展示串口通信原理,无需实际硬件连接。
安装与配置步骤
-
下载安装
从官方或可信来源下载安装包,运行安装程序并遵循提示完成安装,可能需要重启系统。
-
创建虚拟串口
打开VSPD软件,在界面中选择"Add pair"或类似选项,指定端口号(如COM3和COM4),点击"OK"生成。
-
配置参数(可选)
部分高级版本允许设置波特率、数据格式等参数,确保与目标应用程序的配置一致。
-
验证通信
使用串口调试工具(如Putty、Tera Term)分别打开虚拟端口,发送数据测试双向通信是否正常。
注意事项
-
避免与物理串口冲突,选择未占用的COM端口号。
-
部分安全软件可能拦截驱动安装,需临时禁用或添加信任。
-
虚拟串口仅在当前系统生效,关闭软件后端口对自动移除。



2、项目配置文件修改
.pro 文件的作用
Qt项目配置文件(.pro文件)是Qt项目的核心构建配置文件,用于定义项目结构、依赖关系和构建规则。该文件由qmake工具解析,生成适用于不同平台的Makefile或其他构建系统文件。.pro文件的完整语法参考Qt官方文档中的qmake Manual,实际项目中可根据需要组合使用上述配置项。
Qt 中的 SerialPort
Qt 提供了 QSerialPort 类,用于跨平台的串口通信。以下是使用 QSerialPort 的基本方法和常见操作。
可以通过 QSerialPortInfo 获取系统中可用的串口列表:
创建一个 QSerialPort 对象并配置串口参数:
使用 open() 方法打开串口:
写入数据:
读取数据:
使用 close() 方法关闭串口:
QSerialPort 提供了信号用于异步通信:
cpp
#include <QCoreApplication>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QSerialPort serial;
serial.setPortName("COM1");
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
if (!serial.open(QIODevice::ReadWrite)) {
qDebug() << "Failed to open serial port:" << serial.errorString();
return -1;
}
serial.write("Hello, Serial Port!");
if (!serial.waitForBytesWritten(1000)) {
qDebug() << "Write timeout:" << serial.errorString();
}
if (serial.waitForReadyRead(1000)) {
QByteArray response = serial.readAll();
while (serial.waitForReadyRead(10)) {
response += serial.readAll();
}
qDebug() << "Received:" << response;
} else {
qDebug() << "Read timeout:" << serial.errorString();
}
serial.close();
return a.exec();
}


cpp
#include "monitorview.h"
#include "ui_monitorview.h"
#include <QSerialPortInfo>
#include <QSerialPort>
#include <SystemUtils.h>
MonitorView::MonitorView(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MonitorView)
{
ui->setupUi(this);
SystemUtils utils;
utils.SetDropShadowEffect(ui->wdg_link_container,QColor("#33000000"),5);//设置连接设备的阴影效果
// 设置字体图标
QFont font=QFont(QString("zx_icons"),9);
// 监控状态
ui->lbl_status_title_icon->setFont(font);
ui->lbl_status_title_icon->setText(QChar(0xe807));
//串口区域的刷新按钮
QFont font2=QFont(QString("zx_icons"),11);
ui->pb_port_refresh->setFont(font2);
ui->pb_port_refresh->setText(QChar(0xe71e));
// OLED区域标题
ui->lbl_oled_title_icon->setFont(font);
ui->lbl_oled_title_icon->setText(QChar(0xe807));
//设置1-6号灯珠的图标及大小
font.setPixelSize(30);
ui->lbl_light_icon_1->setFont(font);
ui->lbl_light_icon_1->setText(QChar(0xe9e2));
ui->lbl_light_icon_2->setFont(font);
ui->lbl_light_icon_2->setText(QChar(0xe9e2));
ui->lbl_light_icon_3->setFont(font);
ui->lbl_light_icon_3->setText(QChar(0xe9e2));
ui->lbl_light_icon_4->setFont(font);
ui->lbl_light_icon_4->setText(QChar(0xe9e2));
ui->lbl_light_icon_5->setFont(font);
ui->lbl_light_icon_5->setText(QChar(0xe9e2));
ui->lbl_light_icon_6->setFont(font);
ui->lbl_light_icon_6->setText(QChar(0xe9e2));
//加载串口列表
//使用QSerialPortInfo::availablePorts()方法可以获取系统中所有可用的串口。这个方法返回一个QList<QSerialPortInfo>,其中包含了所有串口的信息
// 获取所有可用的串口信息 QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ui->cb_port->addItem(info.portName());
}
//初始化波特率
ui->cb_baud->addItem("2400");
ui->cb_baud->addItem("4800");
ui->cb_baud->addItem("9600");
ui->cb_baud->addItem("19200");
ui->cb_baud->setCurrentText("9600");//设置默认选项
// 初始化校验位列表
ui->cb_parity->addItem("No");
ui->cb_parity->addItem("Odd");
ui->cb_parity->addItem("Even");
ui->cb_parity->addItem("Space");
ui->cb_parity->addItem("Mark");
ui->cb_parity->setCurrentText("No");//设置默认选项
// 初始化数据位列表
ui->cb_data->addItem("5");
ui->cb_data->addItem("6");
ui->cb_data->addItem("7");
ui->cb_data->addItem("8");
ui->cb_data->setCurrentText("8");//设置默认选项
// 初始化停止位列表
ui->cb_stop->addItem("One");
ui->cb_stop->addItem("OneAndHalf");
ui->cb_stop->addItem("Two");
ui->cb_stop->setCurrentText("One"); //设置默认选项
}
MonitorView::~MonitorView()
{
delete ui;
}
//刷新串口列表
void MonitorView::on_pb_port_refresh_clicked()
{
//加载串口列表
ui->cb_port->clear();//清空
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ui->cb_port->addItem(info.portName());
}
}
串口波特率
波特率(Baud Rate)是衡量数据传输速率的参数,表示每秒传输的符号数(或信号变化次数),单位为"波特"(Baud)。它与比特率(Bit Rate)不同,后者表示每秒传输的二进制位数(bps)。两者的关系取决于单个符号携带的比特数:
\\text{比特率} = \\text{波特率} \\times \\text{每符号比特数}
例如,若采用4相调制(每个符号代表2比特),波特率为9600 Baud时,比特率为19200 bps。
波特率与通信配置
在串行通信(如UART)中,波特率需双方设备一致才能正确解码数据。常见标准值包括:
-
1200 Baud
-
9600 Baud(常用默认值)
-
19200 Baud
-
115200 Baud(高速通信)
典型应用场景
-
低速设备:传感器(如温湿度模块)常用9600 Baud。
-
高速传输:视频流或无线通信(如5G)采用高阶调制(如64-QAM),提升比特率但波特率较低。
-
工业协议:Modbus默认波特率为19200 Baud,需避免长距离传输时的信号衰减。
串口校验位
在串口通信中,校验位用于检测数据传输过程中可能出现的错误。校验位通常位于数据位之后,停止位之前,用于验证数据的完整性。
校验位的类型
奇校验(Odd Parity)
校验位设置为使数据位中"1"的总数为奇数。如果数据位中"1"的数量已经是奇数,校验位为"0";否则为"1"。
偶校验(Even Parity)
校验位设置为使数据位中"1"的总数为偶数。如果数据位中"1"的数量已经是偶数,校验位为"0";否则为"1"。
无校验(No Parity)
不启用校验位,数据直接传输。
标记校验(Mark Parity)
校验位固定为"1",通常用于特殊用途。
空格校验(Space Parity)
校验位固定为"0",通常用于特殊用途。
校验位的应用
校验位主要用于检测单比特错误。如果接收方计算的校验结果与接收到的校验位不匹配,说明数据传输过程中可能出现了错误。
校验位的局限性
校验位只能检测奇数个比特错误。如果传输过程中出现偶数个比特错误,校验位无法检测到错误。因此,在高可靠性要求的场景中,可能需要更复杂的校验机制(如CRC)。
串口数据位
串口通信中的数据位(Data Bits)指每个数据帧中实际传输的有效数据位数,通常为5、6、7或8位。数据位的长度决定了单次传输能携带的信息量,例如8位数据位可传输一个完整的ASCII字符。
数据位的常见配置
-
5位:早期电传打字机使用,现已较少见。
-
6位:特定场景或旧设备可能采用。
-
7位:适用于ASCII字符传输(标准ASCII码为7位)。
-
8位:最常用配置,支持二进制数据或扩展ASCII字符集。
数据位与其他参数的关系
数据位需与停止位(Stop Bits)、校验位(Parity Bit)协同配置。例如:
-
无校验位:通常搭配8位数据位和1位停止位(8N1)。
-
偶校验:可能使用7位数据位,校验位补足第8位。
串口停止位
停止位是串行通信中用于标识一个数据帧结束的信号位。它与起始位、数据位和校验位共同构成完整的通信帧。停止位的长度通常为1、1.5或2个比特时间,具体取决于通信协议的配置。
停止位的常见设置
-
1位停止位:最常用的配置,适用于大多数标准通信场景。
-
1.5位停止位:较少使用,主要用于某些特定硬件或历史协议(如老式调制解调器)。
-
2位停止位:用于对时序容错性要求较高的场景,如长距离通信或高噪声环境。
停止位的作用
-
确保接收端能够正确识别数据帧的结束。
-
提供缓冲区,允许接收硬件在下一个起始位前完成数据处理。
-
与波特率共同决定通信的时序稳定性。
3、刷新按钮


4、运行效果




5、小结
串口(Serial Port)是计算机与外部设备进行串行通信的接口,通过逐位传输数据实现通信。常见的串口标准包括RS-232、RS-422和RS-485。串口的通信参数有:波特率(Baud Rate),数据位(Data Bits),停止位(Stop Bits),校验位(Parity Bit)。
- 标准配置:波特率115200,数据位8,停止位1,无校验,无流控。
- 老式设备:波特率9600,数据位7,停止位1,偶校验,硬件流控。
原创不易,打字不易,截图不易,撸码不易,整理不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,灌水,请动动你的金手指,祝您早日实现财务自由。
