添加M1产测设计稿
authorSnickerSun <snickersun@163.com>
Fri, 28 Nov 2025 12:43:53 +0000 (20:43 +0800)
committerSnickerSun <snickersun@163.com>
Fri, 28 Nov 2025 12:43:53 +0000 (20:43 +0800)
docs/m1产测设计/GY-33使用说明v2.pdf [new file with mode: 0644]
docs/m1产测设计/M1 pin定义.xlsx [new file with mode: 0644]
docs/m1产测设计/M1测试方案.ppt [new file with mode: 0644]
docs/m1产测设计/m1_产测日志.txt [moved from docs/m1_产测日志.txt with 100% similarity]
docs/m1产测设计/pin脚图.png [new file with mode: 0644]
rgb_serial_reader.cpp [new file with mode: 0644]
rgb_serial_reader.h [new file with mode: 0644]

diff --git a/docs/m1产测设计/GY-33使用说明v2.pdf b/docs/m1产测设计/GY-33使用说明v2.pdf
new file mode 100644 (file)
index 0000000..db24696
Binary files /dev/null and "b/docs/m1\344\272\247\346\265\213\350\256\276\350\256\241/GY-33\344\275\277\347\224\250\350\257\264\346\230\216v2.pdf" differ
diff --git a/docs/m1产测设计/M1 pin定义.xlsx b/docs/m1产测设计/M1 pin定义.xlsx
new file mode 100644 (file)
index 0000000..ed106c5
Binary files /dev/null and "b/docs/m1\344\272\247\346\265\213\350\256\276\350\256\241/M1 pin\345\256\232\344\271\211.xlsx" differ
diff --git a/docs/m1产测设计/M1测试方案.ppt b/docs/m1产测设计/M1测试方案.ppt
new file mode 100644 (file)
index 0000000..4b23aee
Binary files /dev/null and "b/docs/m1\344\272\247\346\265\213\350\256\276\350\256\241/M1\346\265\213\350\257\225\346\226\271\346\241\210.ppt" differ
diff --git a/docs/m1产测设计/pin脚图.png b/docs/m1产测设计/pin脚图.png
new file mode 100644 (file)
index 0000000..dd06cb1
Binary files /dev/null and "b/docs/m1\344\272\247\346\265\213\350\256\276\350\256\241/pin\350\204\232\345\233\276.png" differ
diff --git a/rgb_serial_reader.cpp b/rgb_serial_reader.cpp
new file mode 100644 (file)
index 0000000..9a8cdfc
--- /dev/null
@@ -0,0 +1,311 @@
+#include "rgb_serial_reader.h"\r
+#include <QDebug>\r
+#include <QMessageBox>\r
+#include <QByteArray>\r
+#include <QDataStream>\r
+#include <QTimer>\r
+\r
+RgbSerialReader::RgbSerialReader(int port_index, QObject *parent)\r
+    : QObject(parent)\r
+    , m_port_index(port_index)\r
+    , m_rgb_serial(new QSerialPort(this))\r
+{\r
+    // 连接串口信号\r
+    connect(m_rgb_serial, &QSerialPort::readyRead, this, &RgbSerialReader::onReadyRead);\r
+    connect(m_rgb_serial, QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::error),\r
+            this, &RgbSerialReader::onError);\r
+}\r
+\r
+RgbSerialReader::~RgbSerialReader()\r
+{\r
+    disconnectPort();\r
+}\r
+\r
+void RgbSerialReader::connectPort(const QString& com_name, int baud_rate)\r
+{\r
+    if (m_rgb_serial->isOpen()) {\r
+        qDebug() << tr("端口%1 RGB串口已经打开,先关闭").arg(m_port_index + 1);\r
+        m_rgb_serial->close();\r
+    }\r
+    \r
+    // 检查是否选择了 "None"\r
+    if (com_name.isEmpty() || com_name == tr("None") || com_name == "None") {\r
+        qDebug() << tr("端口%1未选择RGB串口(选择了None),跳过打开串口操作").arg(m_port_index + 1);\r
+        emit connectionStatusChanged(false);\r
+        return;\r
+    }\r
+    \r
+    qDebug() << tr("=== 开始连接RGB串口%1 ===").arg(m_port_index + 1);\r
+    qDebug() << tr("RGB串口名称:") << com_name;\r
+    qDebug() << tr("波特率:") << baud_rate;\r
+    \r
+    m_rgb_serial->setPortName(com_name);\r
+    m_rgb_serial->setBaudRate(baud_rate);\r
+    m_rgb_serial->setDataBits(QSerialPort::Data8);\r
+    m_rgb_serial->setParity(QSerialPort::NoParity);\r
+    m_rgb_serial->setStopBits(QSerialPort::OneStop);\r
+    m_rgb_serial->setFlowControl(QSerialPort::NoFlowControl);\r
+    m_rgb_serial->setReadBufferSize(MAX_BUFFER_SIZE);\r
+    \r
+    // 清空接收缓冲区\r
+    m_receive_buffer.clear();\r
+    \r
+    if (m_rgb_serial->open(QIODevice::ReadWrite)) {  // RGB串口需要读写(发送指令)\r
+        qDebug() << tr("端口%1 RGB串口打开成功").arg(m_port_index + 1);\r
+        emit connectionStatusChanged(true);\r
+        \r
+        // 连接成功后自动发送初始化指令\r
+        QTimer::singleShot(100, this, [this]() {\r
+            sendCloseLedCommand();      // 关闭LED\r
+            QTimer::singleShot(50, this, [this]() {\r
+                sendSaveLedCommand();   // 保存LED设置\r
+                QTimer::singleShot(50, this, [this]() {\r
+                    sendQueryRgbcCommand();  // 查询RGBC数据\r
+                });\r
+            });\r
+        });\r
+    } else {\r
+        QString errorMsg = tr("端口%1 RGB串口打开失败: %2").arg(m_port_index + 1).arg(m_rgb_serial->errorString());\r
+        qDebug() << errorMsg;\r
+        emit errorOccurred(errorMsg);\r
+        emit connectionStatusChanged(false);\r
+    }\r
+}\r
+\r
+void RgbSerialReader::disconnectPort()\r
+{\r
+    if (m_rgb_serial->isOpen()) {\r
+        qDebug() << tr("端口%1关闭RGB串口").arg(m_port_index + 1);\r
+        m_rgb_serial->close();\r
+        emit connectionStatusChanged(false);\r
+    }\r
+    \r
+    // 清空接收缓冲区\r
+    m_receive_buffer.clear();\r
+}\r
+\r
+void RgbSerialReader::onReadyRead()\r
+{\r
+    const QByteArray data = m_rgb_serial->readAll();\r
+    \r
+    if (data.isEmpty()) {\r
+        return;\r
+    }\r
+    \r
+    // 将新数据添加到缓冲区\r
+    m_receive_buffer.append(data);\r
+    \r
+    // 保持缓冲区大小合理,避免内存溢出\r
+    if (m_receive_buffer.length() > MAX_BUFFER_SIZE) {\r
+        // 保留最近的数据\r
+        m_receive_buffer = m_receive_buffer.right(MAX_BUFFER_SIZE);\r
+        qDebug() << tr("端口%1 RGB串口缓冲区过大,保留最近%2字节").arg(m_port_index + 1).arg(MAX_BUFFER_SIZE);\r
+    }\r
+    \r
+    // 发送原始数据信号(仅发送新接收的数据)\r
+    emit dataReceived(data);\r
+    emit rgbDataReceived(m_port_index, data);\r
+    \r
+    // 解析RGBC数据(从整个缓冲区中查找Byte2=0x15的数据包)\r
+    parseRgbcData(m_receive_buffer);\r
+}\r
+\r
+void RgbSerialReader::onError(QSerialPort::SerialPortError error)\r
+{\r
+    if (error == QSerialPort::NoError) {\r
+        return;\r
+    }\r
+    \r
+    QString errorMsg;\r
+    switch (error) {\r
+    case QSerialPort::DeviceNotFoundError:\r
+        errorMsg = tr("端口%1 RGB串口设备未找到").arg(m_port_index + 1);\r
+        break;\r
+    case QSerialPort::PermissionError:\r
+        errorMsg = tr("端口%1 RGB串口权限错误").arg(m_port_index + 1);\r
+        break;\r
+    case QSerialPort::OpenError:\r
+        errorMsg = tr("端口%1 RGB串口打开错误").arg(m_port_index + 1);\r
+        break;\r
+    case QSerialPort::WriteError:\r
+        errorMsg = tr("端口%1 RGB串口写入错误").arg(m_port_index + 1);\r
+        break;\r
+    case QSerialPort::ReadError:\r
+        errorMsg = tr("端口%1 RGB串口读取错误").arg(m_port_index + 1);\r
+        break;\r
+    case QSerialPort::ResourceError:\r
+        errorMsg = tr("端口%1 RGB串口资源错误(设备可能已断开)").arg(m_port_index + 1);\r
+        break;\r
+    case QSerialPort::UnsupportedOperationError:\r
+        errorMsg = tr("端口%1 RGB串口不支持的操作").arg(m_port_index + 1);\r
+        break;\r
+    case QSerialPort::TimeoutError:\r
+        errorMsg = tr("端口%1 RGB串口超时错误").arg(m_port_index + 1);\r
+        break;\r
+    default:\r
+        errorMsg = tr("端口%1 RGB串口未知错误: %2").arg(m_port_index + 1).arg(error);\r
+        break;\r
+    }\r
+    \r
+    qDebug() << errorMsg;\r
+    emit errorOccurred(errorMsg);\r
+    \r
+    // 如果是资源错误,自动断开连接\r
+    if (error == QSerialPort::ResourceError) {\r
+        disconnectPort();\r
+    }\r
+}\r
+\r
+void RgbSerialReader::sendCloseLedCommand()\r
+{\r
+    if (!m_rgb_serial || !m_rgb_serial->isOpen()) {\r
+        return;\r
+    }\r
+    \r
+    // 关闭LED指令: A5 6A 0F\r
+    QByteArray cmd;\r
+    cmd.append((char)0xA5);\r
+    cmd.append((char)0x6A);\r
+    cmd.append((char)0x0F);\r
+    \r
+    qint64 bytesWritten = m_rgb_serial->write(cmd);\r
+    if (bytesWritten == cmd.size()) {\r
+        qDebug() << tr("端口%1 RGB串口发送关闭LED指令成功").arg(m_port_index + 1);\r
+    } else {\r
+        qDebug() << tr("端口%1 RGB串口发送关闭LED指令失败").arg(m_port_index + 1);\r
+    }\r
+}\r
+\r
+void RgbSerialReader::sendSaveLedCommand()\r
+{\r
+    if (!m_rgb_serial || !m_rgb_serial->isOpen()) {\r
+        return;\r
+    }\r
+    \r
+    // 保存LED亮度设置指令: A5 CC 71\r
+    QByteArray cmd;\r
+    cmd.append((char)0xA5);\r
+    cmd.append((char)0xCC);\r
+    cmd.append((char)0x71);\r
+    \r
+    qint64 bytesWritten = m_rgb_serial->write(cmd);\r
+    if (bytesWritten == cmd.size()) {\r
+        qDebug() << tr("端口%1 RGB串口发送保存LED设置指令成功").arg(m_port_index + 1);\r
+    } else {\r
+        qDebug() << tr("端口%1 RGB串口发送保存LED设置指令失败").arg(m_port_index + 1);\r
+    }\r
+}\r
+\r
+void RgbSerialReader::sendQueryRgbcCommand()\r
+{\r
+    if (!m_rgb_serial || !m_rgb_serial->isOpen()) {\r
+        return;\r
+    }\r
+    \r
+    // 查询RGBC原始AD值指令: A5 51 F6\r
+    QByteArray cmd;\r
+    cmd.append((char)0xA5);\r
+    cmd.append((char)0x51);\r
+    cmd.append((char)0xF6);\r
+    \r
+    qint64 bytesWritten = m_rgb_serial->write(cmd);\r
+    if (bytesWritten == cmd.size()) {\r
+        qDebug() << tr("端口%1 RGB串口发送查询RGBC指令成功").arg(m_port_index + 1);\r
+    } else {\r
+        qDebug() << tr("端口%1 RGB串口发送查询RGBC指令失败").arg(m_port_index + 1);\r
+    }\r
+}\r
+\r
+bool RgbSerialReader::findRgbcFrame(const QByteArray& buffer, int& startPos, int& endPos)\r
+{\r
+    // 查找数据帧:5A 5A 15 XX ... (Byte2=0x15)\r
+    // 帧头:5A 5A\r
+    // Byte2: 0x15 (RGBC数据类型)\r
+    // Byte3: 数据长度(不包括帧头、Byte2和长度本身)\r
+    \r
+    startPos = -1;\r
+    endPos = -1;\r
+    \r
+    // 查找帧头 5A 5A,至少需要4个字节才能判断\r
+    for (int i = 0; i <= buffer.size() - 4; i++) {\r
+        if ((quint8)buffer[i] == 0x5A && (quint8)buffer[i + 1] == 0x5A) {\r
+            // 检查Byte2是否为0x15\r
+            if ((quint8)buffer[i + 2] == 0x15) {\r
+                // 获取数据长度(Byte3)\r
+                quint8 dataLength = (quint8)buffer[i + 3];\r
+                // 完整帧长度 = 帧头(2) + Byte2(1) + 长度(1) + 数据(dataLength) = 4 + dataLength\r
+                int frameLength = 4 + dataLength;\r
+                \r
+                // 检查是否有足够的数据\r
+                if (i + frameLength <= buffer.size()) {\r
+                    startPos = i;\r
+                    endPos = i + frameLength;\r
+                    return true;\r
+                } else {\r
+                    // 数据不完整,等待更多数据\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+    return false;\r
+}\r
+\r
+void RgbSerialReader::parseRgbcData(const QByteArray& buffer)\r
+{\r
+    int startPos, endPos;\r
+    \r
+    // 查找所有完整的RGBC数据帧(Byte2=0x15)\r
+    // 注意:这里使用局部变量buffer,实际修改的是成员变量m_receive_buffer\r
+    QByteArray tempBuffer = buffer;\r
+    \r
+    while (findRgbcFrame(tempBuffer, startPos, endPos)) {\r
+        if (startPos >= 0 && endPos > startPos && endPos <= tempBuffer.size()) {\r
+            // 提取完整的数据帧\r
+            QByteArray frame = tempBuffer.mid(startPos, endPos - startPos);\r
+            \r
+            // 验证帧格式:5A 5A 15 XX [数据]\r
+            // 至少需要12字节:帧头(2) + Byte2(1) + 长度(1) + RGBC数据(8) = 12\r
+            if (frame.size() >= 12) {\r
+                // 解析RGBC数据\r
+                // 帧格式:5A 5A 15 08 R_H R_L G_H G_L B_H B_L C_H C_L ...\r
+                // 索引:   0   1  2  3   4   5   6   7   8   9  10  11\r
+                \r
+                // 提取RGBC数据(每个值2字节,高字节在前)\r
+                quint8 r_high = (quint8)frame[4];\r
+                quint8 r_low = (quint8)frame[5];\r
+                quint8 g_high = (quint8)frame[6];\r
+                quint8 g_low = (quint8)frame[7];\r
+                quint8 b_high = (quint8)frame[8];\r
+                quint8 b_low = (quint8)frame[9];\r
+                quint8 c_high = (quint8)frame[10];\r
+                quint8 c_low = (quint8)frame[11];\r
+                \r
+                // 计算RGBC值:高8位左移8位后与低8位或运算\r
+                quint16 red = ((quint16)r_high << 8) | r_low;\r
+                quint16 green = ((quint16)g_high << 8) | g_low;\r
+                quint16 blue = ((quint16)b_high << 8) | b_low;\r
+                quint16 clear = ((quint16)c_high << 8) | c_low;\r
+                \r
+                // 输出调试信息(包含原始十六进制数据)\r
+                QString hexFrame = frame.toHex(' ').toUpper();\r
+                qDebug() << tr("端口%1 RGB串口解析RGBC数据帧: %2").arg(m_port_index + 1).arg(hexFrame);\r
+                qDebug() << tr("端口%1 RGB串口RGBC值: R=%2, G=%3, B=%4, C=%5")\r
+                         .arg(m_port_index + 1).arg(red).arg(green).arg(blue).arg(clear);\r
+                \r
+                // 发送解析后的RGBC数据信号\r
+                emit rgbcDataParsed(m_port_index, red, green, blue, clear);\r
+            }\r
+            \r
+            // 从临时缓冲区中移除已处理的数据帧,继续查找\r
+            tempBuffer.remove(startPos, endPos - startPos);\r
+            \r
+            // 同时从成员变量缓冲区中移除已处理的数据帧\r
+            m_receive_buffer.remove(startPos, endPos - startPos);\r
+        } else {\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
diff --git a/rgb_serial_reader.h b/rgb_serial_reader.h
new file mode 100644 (file)
index 0000000..f294cab
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef RGB_SERIAL_READER_H\r
+#define RGB_SERIAL_READER_H\r
+\r
+#include <QObject>\r
+#include <QSerialPort>\r
+#include <QByteArray>\r
+#include <QString>\r
+\r
+// RGB串口读取器类 - 专门处理RGB串口的数据读取\r
+class RgbSerialReader : public QObject\r
+{\r
+    Q_OBJECT\r
+\r
+public:\r
+    explicit RgbSerialReader(int port_index, QObject *parent = nullptr);\r
+    ~RgbSerialReader();\r
+\r
+    // 端口索引 (0-3)\r
+    int portIndex() const { return m_port_index; }\r
+\r
+    // 串口对象访问\r
+    QSerialPort* serialPort() const { return m_rgb_serial; }\r
+\r
+    // 公共接口函数\r
+    void connectPort(const QString& com_name, int baud_rate);\r
+    void disconnectPort();\r
+    bool isConnected() const { return m_rgb_serial && m_rgb_serial->isOpen(); }\r
+    \r
+    // RGB传感器控制指令\r
+    void sendCloseLedCommand();                         // 关闭LED指令: A5 6A 0F\r
+    void sendSaveLedCommand();                          // 保存LED亮度设置: A5 CC 71\r
+    void sendQueryRgbcCommand();                        // 查询RGBC原始AD值: A5 51 F6\r
+\r
+signals:\r
+    // 数据接收信号\r
+    void dataReceived(const QByteArray& data);           // 接收到原始数据\r
+    void textReceived(const QString& text);              // 接收到文本数据\r
+    void rgbDataReceived(int port_index, const QByteArray& data);  // 带端口索引的数据信号\r
+    \r
+    // RGBC数据解析信号(当Byte2=0x15时)\r
+    void rgbcDataParsed(int port_index, quint16 red, quint16 green, quint16 blue, quint16 clear);  // 解析后的RGBC数据\r
+    \r
+    // 状态信号\r
+    void connectionStatusChanged(bool connected);        // 连接状态变化\r
+    void errorOccurred(const QString& error);            // 错误信号\r
+\r
+private slots:\r
+    void onReadyRead();                                  // 串口数据就绪\r
+    void onError(QSerialPort::SerialPortError error);   // 串口错误处理\r
+\r
+private:\r
+    // 端口索引 (0-3)\r
+    int m_port_index;\r
+\r
+    // 串口对象\r
+    QSerialPort *m_rgb_serial;\r
+\r
+    // 数据缓冲区(用于处理分包数据)\r
+    QByteArray m_receive_buffer;\r
+    \r
+    // 最大缓冲区大小(防止内存溢出)\r
+    static const int MAX_BUFFER_SIZE = 32768;  // 32KB\r
+    \r
+    // 数据解析函数\r
+    void parseRgbcData(const QByteArray& data);          // 解析RGBC数据(查找Byte2=0x15的数据包)\r
+    bool findRgbcFrame(const QByteArray& buffer, int& startPos, int& endPos);  // 查找完整的RGBC数据帧\r
+};\r
+\r
+#endif // RGB_SERIAL_READER_H\r
+\r