CameraGrabber/parameterhandler.cpp

179 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ParameterHandler.h"
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
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<QSerialPort::SerialPortError>::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();
}
}
}