You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UART多文件传输异常:Windows到BeagleBone未生成独立文件求助

解决UART多文件传输合并存储问题

问题根源

当前协议逻辑存在两处关键错误:

  • 发送端在文件内容之前发送0x03标记,但接收端把0x03当作文件结束标记,导致刚进入数据接收状态就触发文件关闭,后续文件内容无法写入对应文件。
  • 接收端的filenameBuffer在拼接路径后未保留原文件名,后续文件会复用被修改后的路径,导致内容混乱存储。

修复方案

1. 发送端Python代码修改

调整协议逻辑:将0x03作为文件内容结束标记,放在文件数据之后发送,而非之前。

import serial
import time

def send_file(serial_port, file_name):
    try:
        # 发送文件开始标记
        serial_port.write(bytes([0x01]))
        # 发送文件名
        serial_port.write(file_name.encode())
        # 发送文件名结束标记
        serial_port.write(bytes([0x02]))

        # 打开文件并发送内容
        with open(f"C:/Users/HP/OneDrive/Desktop/DRS_Database/{file_name}", "rb") as file:
            file_data = file.read()
            serial_port.write(file_data)
        
        # 发送文件内容结束标记(放在数据之后)
        serial_port.write(bytes([0x03]))
        print(f"{file_name} 发送成功")
    except FileNotFoundError:
        print(f"未找到文件 {file_name}")

def send_files(serial_port, filenames):
    for file_name in filenames:
        send_file(serial_port, file_name)
        time.sleep(1)  # 给接收端留处理时间

    # 发送全部传输完成标记
    serial_port.write(bytes([0x04]))

# 初始化串口
ser = serial.Serial('COM11', 9600)
file_names = ["DIA_ID.TXT", "OP_REC.TXT", "DIA_REC.TXT", "PAT_REC.TXT", "JAR_REC.TXT", "PRO_REC.TXT"]

send_files(ser, file_names)
ser.close()

2. 接收端C代码修改

  • 修正DATA状态下0x03的逻辑:收到0x03时关闭当前文件,回到IDLE状态准备接收下一个文件。
  • 新增独立变量存储完整文件路径,避免修改原文件名缓冲区。
  • 每次进入FILENAME状态时重置文件指针,避免残留状态影响下一个文件。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

#define UART_PORT "/dev/ttyS1"
#define BAUD_RATE B9600
#define UART_BUFFER_SIZE 8192

enum State {
    IDLE,
    FILENAME,
    DATA
};

char readByte(int uart_fd) {
    char byte;
    ssize_t bytesRead = read(uart_fd, &byte, 1);

    if (bytesRead < 0) {
        perror("读取UART失败");
        exit(EXIT_FAILURE);
    }

    return byte;
}

void receiveAndStoreFilesOverUART(const char *folderPath) {
    int uart_fd = open(UART_PORT, O_RDWR | O_NOCTTY);
    struct termios uart_config;

    if (uart_fd < 0) {
        perror("打开UART端口失败");
        exit(EXIT_FAILURE);
    }

    // 配置UART参数
    if (tcgetattr(uart_fd, &uart_config) < 0) {
        perror("获取UART配置失败");
        close(uart_fd);
        exit(EXIT_FAILURE);
    }

    cfsetispeed(&uart_config, BAUD_RATE);
    cfsetospeed(&uart_config, BAUD_RATE);
    uart_config.c_cflag &= ~PARENB;
    uart_config.c_cflag &= ~CSTOPB;
    uart_config.c_cflag &= ~CSIZE;
    uart_config.c_cflag |= CS8;
    uart_config.c_cflag &= ~CRTSCTS;
    uart_config.c_cflag |= CREAD | CLOCAL;
    uart_config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    uart_config.c_cc[VMIN] = 1;
    uart_config.c_cc[VTIME] = 0;

    if (tcsetattr(uart_fd, TCSANOW, &uart_config) < 0) {
        perror("设置UART配置失败");
        close(uart_fd);
        exit(EXIT_FAILURE);
    }

    enum State state = IDLE;
    int finished = 0;
    char filenameBuffer[256];
    char fullFilePath[256]; // 独立存储完整路径,不修改原文件名缓冲区
    FILE *file = NULL;

    while (!finished) {
        char byte = readByte(uart_fd);

        switch (state) {
            case IDLE:
                if (byte == 0x01) {
                    state = FILENAME;
                    filenameBuffer[0] = '\0';
                    file = NULL; // 重置文件指针
                    printf("进入文件名接收状态\n");
                } else if (byte == 0x04) {
                    finished = 1;
                    printf("传输结束,回到空闲状态\n");
                }
                break;

            case FILENAME:
                if (byte == 0x02) {
                    // 拼接完整文件路径,保留原filenameBuffer
                    snprintf(fullFilePath, sizeof(fullFilePath), "%s/%s", folderPath, filenameBuffer);
                    state = DATA;
                    printf("进入数据接收状态,目标文件:%s\n", fullFilePath);
                } else if (byte == 0x04) {
                    finished = 1;
                    printf("传输终止,回到空闲状态\n");
                } else {
                    // 防止缓冲区溢出
                    if (strlen(filenameBuffer) < sizeof(filenameBuffer)-1) {
                        strncat(filenameBuffer, &byte, 1);
                    }
                }
                break;

            case DATA:
                if (byte == 0x03) {
                    // 收到文件结束标记,关闭文件
                    if (file != NULL) {
                        fclose(file);
                        file = NULL;
                        printf("文件写入完成并关闭\n");
                    }
                    state = IDLE;
                } else if (byte == 0x04) {
                    // 收到终止信号,清理资源
                    if (file != NULL) {
                        fclose(file);
                        file = NULL;
                        printf("关闭当前文件\n");
                    }
                    finished = 1;
                } else {
                    // 仅第一次写入时打开文件
                    if (file == NULL) {
                        file = fopen(fullFilePath, "wb");
                        if (file == NULL) {
                            perror("打开文件失败");
                            finished = 1;
                        }
                    }
                    if (file != NULL) {
                        fwrite(&byte, 1, 1, file);
                    }
                }
                break;
        }
    }

    close(uart_fd);
}

int main(void) {
    const char *storageFolderPath = "/home/debian/NEW";
    receiveAndStoreFilesOverUART(storageFolderPath);
    printf("接收完成\n");
    return 0;
}

验证步骤

  1. 重新编译BeagleBone端C代码并运行。
  2. 运行Windows端Python脚本。
  3. 查看/home/debian/NEW目录,确认6个文件均独立生成且内容与原文件一致。

内容的提问来源于stack exchange,提问作者Avinash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:14:53