Skip to content
cpp
//
// Created by knight on 2023/11/10.
//
#include <windows.h>
#include <iostream>
#include <vector>

// 设置开始标识位
const char PACKET_START[] = {0x4d, 0x45, 0x50};
const char PACKET_START_LENGTH = sizeof(PACKET_START);

// 设置结束标识位
const char PACKET_END[] = {0x53, 0x4C, 0x44};
const char PACKET_END_LENGTH = sizeof(PACKET_END);

const int PACKET_LENGTH = 1207;


int main(int argc, char *argv[]) {
    // 创建串口句柄
    HANDLE serialHandle = CreateFile("COM4", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                                     NULL);

    if (serialHandle == INVALID_HANDLE_VALUE) {
        std::cout << "Failed to open serial port." << std::endl;
        return -1;
    }

    DCB dcbSerialParams = {0};
    // 设置结构体长度
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

    // 使用GetCommState函数获取当前串口的配置参数,并将其存储到dcbSerialParams中
    GetCommState(serialHandle, &dcbSerialParams);

    // 设置串口的波特率为921600,即设置通信速率为921600 bps
    dcbSerialParams.BaudRate = 921600;
    // 将数据位设置为8位
    dcbSerialParams.ByteSize = 8;
    // 设置停止位为1.5个位
    dcbSerialParams.StopBits = ONE5STOPBITS;
    // 设置奇偶校验位为无校验。
    dcbSerialParams.Parity = NOPARITY;

    // 将配置好的参数应用到串口
    SetCommState(serialHandle, &dcbSerialParams);

    DWORD bytesRead;

    std::vector<char> receivedData;
    int dataSize = 0;

    std::vector<char> buffer(PACKET_LENGTH);
    while (ReadFile(serialHandle, buffer.data(), PACKET_LENGTH, &bytesRead, NULL)) {
        // 追加接收到的数据到 receivedData
        receivedData.insert(receivedData.end(), buffer.begin(), buffer.begin() + bytesRead);
        dataSize += static_cast<int>(bytesRead);

        // 查找完整的包
        int headerIndex;  // 头部索引,用于记录找到的包的起始位置
        int packetSize;  // 包大小,用于记录找到的包的长度

        // 如果数据大小比包长度小则继续接收
        if (dataSize < PACKET_LENGTH) {
            continue;
        }

        // 查找完整的包
        for (int i = 0; i < dataSize - PACKET_LENGTH; ++i) {
            if (receivedData[i] != PACKET_START[0] || receivedData[i + 1] != PACKET_START[1] ||
                receivedData[i + 2] != PACKET_START[2]) {
                continue;
            }

            // 包起始位置
            headerIndex = i;
            packetSize = i + PACKET_LENGTH;

            // 在剩余数据中查找结束标记
            for (int j = packetSize; j <= dataSize - PACKET_LENGTH; ++j) {
                if (receivedData[j] == PACKET_END[0] && receivedData[j + 1] == PACKET_END[1] &&
                    receivedData[j + 2] == PACKET_END[2]) {
                    // 包结束标记
                    packetSize = j + PACKET_LENGTH;
                    break;
                }
            }

            if (packetSize - headerIndex == PACKET_LENGTH) {
                // 获取去除头尾的数据包
                std::vector<char> packet(receivedData.begin() + headerIndex + PACKET_START_LENGTH,
                                         receivedData.begin() + packetSize - PACKET_END_LENGTH);
                // todo 处理数据包

                dataSize = static_cast<int>(receivedData.size());

                if (dataSize < PACKET_LENGTH) {
                    break;
                }
            }

            // 移除处理过的当前包
            receivedData.erase(receivedData.begin(), receivedData.begin() + packetSize);

            // 重新检查剩余数据中是否存在完整的包
            i = -1;
        }

    }

}