串口通信是计算机与外部设备进行数据交换的一种基础通信方式。它使用串行通信协议,其中数据按位顺序传输,通常用于较低速率的通信。串口通信广泛应用于各种设备,如打印机、鼠标、调制解调器等
串口通信通常使用 RS-232、RS-422 或 RS-485 等标准。其中,RS-232 是最常用的串口通信标准,它在计算机、通信设备和其他类型的设备之间广泛使用。
- 对于 DB9 连接器:
- 引脚 2 是接收数据(RXD)
- 引脚 3 是发送数据(TXD)
- 引脚 5 是地线(GND)
- 对于 DB25 连接器:
- 引脚 2 是发送数据(TXD)
- 引脚 3 是接收数据(RXD)
- 引脚 7 是地线(GND)
数据位是串口通信中每个数据包的大小,表示每个数据字节中用于承载信息的位数。常见的数据位设置有 7 位或 8 位。例如,8 数据位意味着每个数据字节包含 8 个位。
奇偶校验位是一种错误检测机制。它在每个数据字节后添加一个额外的校验位,用于检测数据传输过程中的单比特错误。奇偶校验可以是无校验、奇校验或偶校验。
停止位用于标记每个数据包的结束。它在每个数据字节后添加一定数量的额外位,以指示数据包的终止。常见的停止位设置有 1 位、1.5 位和 2 位。
流控制是用于管理数据传输速率和确保数据完整性的一种机制。它可以防止发送方在接收方来得及处理之前发送过多数据。流控制可以是无流控制、硬件流控制(RTS/CTS)或软件流控制(XON/XOFF)。
波特率是衡量串口通信速度的单位,表示每秒钟可以传输多少比特(位)的数据。常见的波特率设置有 9600、19200、38400、57600 和 115200 等。选择合适的波特率取决于设备的能力和通信距离。
串口名是用于标识计算机上特定串口的名称。在 Windows 系统中,串口名通常是以 “COM” 开头的,如 “COM1”、“COM2” 等。在 Unix/Linux 系统中,串口名通常以 “/dev/tty” 开头,如 “/dev/ttyS0”、“/dev/ttyUSB0” 等。
这些参数共同定义了串口通信的基本特性,包括数据的格式、速率和传输控制方式。正确配置这些参数对于确保串口通信的可靠性和效率至关重要。
CH340 是一种常见的 USB 转串口芯片,广泛用于提供 USB 到串行通信的接口
http://sparks.gogo.co.nz/ch340.html
- VCC:电源输入,通常为 3.3V 或 5V。
TXD (Transmit Data):数据发送线,用于发送数据到另一设备
RXD (Receive Data):数据接收线,用于接收来自另一设备的数据。
GND (Ground):地线,用于电气接地
USB 转 TTL 串口模块(如基于 CH340 芯片的模块)可以用来将 USB 接口转换为 TTL 串口(即逻辑电平串口)。这种模块通常用于连接电脑的 USB 端口和使用 TTL 电平通信的设备,如微控制器或其他串口设备。以下是 USB 转 TTL 串口模块(CH340)的一般接线方法:
USB 转 TTL 模块(CH340)的典型管脚
连接 VCC 和 GND:
连接 TXD 和 RXD:
这种交叉连接确保一方的发送线连接到另一方的接收线。
连接流控制引脚(可选):
在连接之前,请检查目标设备的文档以确认正确的接线方法。每个设备的接线要求可能略有不同。
QSerialPort(QObject *parent = nullptr) // 构造函数,创建一个 QSerialPort 对象。
void setPortName(const QString &name) // 设置串口的端口名。
QString portName() const // 获取当前串口的端口名。
void setBaudRate(qint32 baudRate, QSerialPort::Directions directions = AllDirections) // 设置波特率。
qint32 baudRate(QSerialPort::Directions directions = AllDirections) const // 获取当前波特率。
void setDataBits(QSerialPort::DataBits dataBits) // 设置数据位。
QSerialPort::DataBits dataBits() const // 获取当前设置的数据位。
void setParity(QSerialPort::Parity parity) // 设置奇偶校验位。
QSerialPort::Parity parity() const // 获取当前奇偶校验设置。
void setStopBits(QSerialPort::StopBits stopBits) // 设置停止位。
QSerialPort::StopBits stopBits() const // 获取当前停止位设置。
void setFlowControl(QSerialPort::FlowControl flowControl) // 设置流控制。
QSerialPort::FlowControl flowControl() const // 获取当前流控制设置。
bool open(QIODevice::OpenMode mode) // 打开串口,设置打开模式(读、写、读写)。
void close() // 关闭串口。
bool isOpen() const // 检查串口是否打开。
bool isReadable() const // 检查串口是否可读。
bool isWritable() const // 检查串口是否可写。
bool writeData(const char *data, qint64 len) // 向串口写入数据。
bool readData(char *data, qint64 maxSize) // 从串口读取数据。
QByteArray readAll() // 读取串口接收到的所有数据。
qint64 bytesAvailable() const // 获取可读取的字节数。
bool waitForReadyRead(int msecs) // 等待数据可读,带有超时。
bool waitForBytesWritten(int msecs) // 等待数据写入完成,带有超时。
QSerialPort::SerialPortError error() const // 获取当前的错误状态。
void clearError() // 清除当前的错误状态。
static QList<QSerialPortInfo> availablePorts() // 获取系统中所有可用的串口列表。
QString portName() const // 获取串口的端口名。
QString description() const // 获取串口的描述信息。
QString manufacturer() const // 获取串口的制造商信息。
QString serialNumber() const // 获取串口的序列号。
QString systemLocation() const // 获取串口在系统中的位置。
qint16 vendorIdentifier() const // 获取串口的供应商标识符。
qint16 productIdentifier() const // 获取串口的产品标识符。
bool hasVendorIdentifier() const // 检查是否有供应商标识符。
bool hasProductIdentifier() const // 检查是否有产品标识符。
bool isBusy() const // 检查串口是否正在使用中。
void readyRead() // 当串口有数据可读时发出的信号。
void bytesWritten(qint64 bytes) // 当串口有数据写入时发出的信号。
void errorOccurred(QSerialPort::SerialPortError error) // 当串口发生错误时发出的信号。
这些函数提供了在 Qt 中进行串口通信所需的基本功能,包括配置串口参数、打开/关闭串口、读写数据以及处理错误和事件。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class SerialPortWidget : public QWidget
{
Q_OBJECT
public:
SerialPortWidget(QWidget *parent = nullptr) : QWidget(parent)
{
serial = new QSerialPort(this);
auto layout = new QVBoxLayout(this);
auto sendButton = new QPushButton(tr("Send"), this);
auto refreshButton = new QPushButton(tr("Refresh Ports"), this);
comboBox = new QComboBox(this);
textEdit = new QTextEdit(this);
textEdit->setReadOnly(true);
layout->addWidget(new QLabel(tr("Select Serial Port:")));
layout->addWidget(comboBox);
layout->addWidget(sendButton);
layout->addWidget(refreshButton);
layout->addWidget(textEdit);
refreshSerialPorts();
connect(sendButton, &QPushButton::clicked, this, &SerialPortWidget::sendData);
connect(refreshButton, &QPushButton::clicked, this, &SerialPortWidget::refreshSerialPorts);
//串口可以读取事件
connect(serial, &QSerialPort::readyRead, this, &SerialPortWidget::readData);
//串口发生错误
connect(serial, &QSerialPort::errorOccurred, this, &SerialPortWidget::handleError);
}
private slots:
void sendData()
{
QString data = "Hello, Serial Port!";
serial->write(data.toLocal8Bit());
}
void readData()
{
QByteArray data = serial->readAll();
textEdit->append(QString(data));
}
void handleError(QSerialPort::SerialPortError error)
{
if (error == QSerialPort::ResourceError) {
QMessageBox::critical(this, tr("Critical Error"), serial->errorString());
serial->close();
}
}
void refreshSerialPorts()
{
comboBox->clear();
//获取所有可用串口
const auto infos = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo &info : infos) {
comboBox->addItem(info.portName());
}
}
void openSerialPort()
{
//打开串口名
serial->setPortName(comboBox->currentText());
//波特率
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)) {
QMessageBox::critical(this, tr("Error"), serial->errorString());
return;
}
}
void closeSerialPort()
{
if (serial->isOpen())
serial->close();
}
private:
QSerialPort *serial;
QTextEdit *textEdit;
QComboBox *comboBox;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
SerialPortWidget widget;
widget.show();
return app.exec();
}
串口枚举和检测:
QSerialPortInfo
类可以用来获取系统中所有可用串口的详细信息,包括端口名、描述、制造商等。异步通信:
readyRead()
信号可用于在有数据可读时通知应用程序。线程和串口通信:
错误处理:
QSerialPort
提供了 errorOccurred()
信号和 error()
方法来报告和查询错误状态。信号调制和解调:
跨平台兼容性:
测试和调试: