#include "ParameterHandler.h" #include #include #include ParameterHandler::ParameterHandler(QObject *parent) : QObject(parent) , m_serialPort(new QSerialPort(this)) { // 将 QSerialPort 的 readyRead 信号连接到槽函数,用于数据接收 connect(m_serialPort, &QSerialPort::readyRead, this, &ParameterHandler::handleReadyRead); // 将 QSerialPort 的 errorOccurred 信号连接到槽函数,用于错误处理 // 使用 QOverload 确保连接到正确的重载函数 connect(m_serialPort, QOverload::of(&QSerialPort::errorOccurred), this, &ParameterHandler::handleError); } ParameterHandler::~ParameterHandler() { // 析构时确保串口关闭 closePort(); // m_serialPort 的父对象是 ParameterHandler (this),所以它会被 QObject 机制自动删除。 } /** * @brief 静态函数实现:获取系统上所有可用串口的名称列表 * @return 包含所有可用串口名称的 QStringList */ QStringList ParameterHandler::getAvailablePortNames() { QStringList portNames; // 使用 QSerialPortInfo::availablePorts() 获取可用串口列表 const auto serialPortInfos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &portInfo : serialPortInfos) { portNames << portInfo.portName(); } return portNames; } bool ParameterHandler::openPort(const QString &portName) { // 如果串口已打开,先关闭 if (m_serialPort->isOpen()) { m_serialPort->close(); } m_serialPort->setPortName(portName); // 1. 尝试打开串口,以读写模式 if (!m_serialPort->open(QIODevice::ReadWrite)) { QString errorMsg = QString("无法打开串口 %1: %2").arg(portName).arg(m_serialPort->errorString()); qWarning() << errorMsg; emit errorOccurred(errorMsg); return false; } // --- 2. 串口配置(根据您的要求) --- // 波特率: 115200 if (!m_serialPort->setBaudRate(QSerialPort::Baud115200)) { qWarning() << "设置波特率失败:" << m_serialPort->errorString(); goto config_error; } // 数据位: 8 bit if (!m_serialPort->setDataBits(QSerialPort::Data8)) { qWarning() << "设置数据位失败:" << m_serialPort->errorString(); goto config_error; } // 校验位: 无校验 (No Parity)。 忽略“1bit校验位”而采用“无校验” if (!m_serialPort->setParity(QSerialPort::NoParity)) { qWarning() << "设置校验位失败:" << m_serialPort->errorString(); goto config_error; } // 停止位: 1 bit if (!m_serialPort->setStopBits(QSerialPort::OneStop)) { qWarning() << "设置停止位失败:" << m_serialPort->errorString(); goto config_error; } // 流量控制: 无流量控制 (No Flow Control) if (!m_serialPort->setFlowControl(QSerialPort::NoFlowControl)) { qWarning() << "设置流控制失败:" << m_serialPort->errorString(); goto config_error; } qDebug() << "串口" << portName << "成功打开并配置为 115200/8/N/1"; return true; config_error: // 配置失败时的错误处理 QString errMsg = QString("串口配置失败: %1").arg(m_serialPort->errorString()); qCritical() << errMsg; m_serialPort->close(); // 配置失败则关闭串口 emit errorOccurred(errMsg); return false; } void ParameterHandler::closePort() { if (m_serialPort->isOpen()) { m_serialPort->close(); qDebug() << "串口" << m_serialPort->portName() << "已关闭"; } } bool ParameterHandler::isPortOpen() const { return m_serialPort->isOpen(); } qint64 ParameterHandler::writeData(const QByteArray &data) { if (!m_serialPort->isOpen()) { qWarning() << "写入失败: 串口未打开"; emit errorOccurred("写入失败: 串口未打开。"); return -1; } qint64 bytesWritten = m_serialPort->write(data); if (bytesWritten == -1) { // 写入操作本身出错 QString errorMsg = QString("写入数据时出错: %1").arg(m_serialPort->errorString()); qWarning() << errorMsg; emit errorOccurred(errorMsg); } else if (bytesWritten != data.size()) { // 写入的数据量不完整 qWarning() << "警告: 仅写入了部分数据。期望:" << data.size() << "实际:" << bytesWritten; } else { qDebug() << "成功写入" << bytesWritten << "字节数据:" << data.toHex().toUpper(); } // 等待数据发送完成,防止在主线程中阻塞太久,设置一个较短的超时 m_serialPort->waitForBytesWritten(10); return bytesWritten; } QString ParameterHandler::portName() const { return m_serialPort->portName(); } void ParameterHandler::handleReadyRead() { // 读取所有等待中的数据 QByteArray data = m_serialPort->readAll(); qDebug() << "接收到数据,字节数:" << data.size() << "数据(Hex):" << data.toHex().toUpper(); // 发出信号通知外部有新数据 emit dataReceived(data); } void ParameterHandler::handleError(QSerialPort::SerialPortError error) { // 忽略 NoError,只处理实际错误 if (error != QSerialPort::NoError && m_serialPort->isOpen()) { QString errorString = m_serialPort->errorString(); qCritical() << "串口发生错误:" << errorString << "(错误码:" << error << ")"; // 发出信号通知外部错误 emit errorOccurred(errorString); // 如果是资源错误(例如设备被拔出),则自动关闭串口 if (error == QSerialPort::ResourceError) { qCritical() << "资源错误,自动关闭串口。"; m_serialPort->close(); } } }