1、背景
当在裸机环境下实现SD卡或者U盘数据存储,在文件规模较大时,单片机自身资源的限制,其运行实时性和响应性将变得很重要。
2、场景模拟说
并举一个读取100000行,字段个数为100个,csv的文件格式,在单片机中裸机环境下进行实现,实现跨块读取和解析。同时满足通过串口来进行循环调取数据
3、实现解决方案:
三级缓存机制(文件系统缓冲区、应用层环形缓冲区、行解析缓存)
4、代码
/***********************************************
* CSV解析通信系统 - 三级缓存机制实现
* 版本:V1.2
* 特性:
* 1. 支持百万级CSV文件处理
* 2. 响应时间<50ms
* 3. 内存占用<2KB
***********************************************/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
/***********************************************
* 硬件相关配置(根据实际平台调整)
***********************************************/
#define UART_RX_BUF_SIZE 128 // 串口接收缓冲区
#define UART_TX_BUF_SIZE 512 // 串口发送缓冲区
#define FILE_READ_BUF_SIZE 256 // 文件读取缓冲区
#define LINE_PARSE_BUF_SIZE 1024 // 行解析缓冲区(需>最大行长度)
#define MAX_COLS_PER_LINE 100 // 每行最大列数
#define CSV_CMD_HEAD 0x55 // 命令包头
#define CSV_CMD_TAIL 0xDD // 命令包尾
#define MAX_LINES_PER_RESPONSE 10 // 单次响应最大行数
/***********************************************
* 数据结构定义
***********************************************/
#pragma pack(push, 1)
typedef struct
{
uint32_t uStartLine; // 起始行号(大端)
uint32_t uEndLine; // 结束行号(大端)
} tCsvCmdBody; // 命令体结构
typedef struct
{
uint8_t uHeader; // 0x55
tCsvCmdBody tBody; // 命令体
uint8_t uTail; // 0xDD
} tCsvCommand; // 完整命令结构
#pragma pack(pop)
typedef enum
{
CSV_PARSE_IDLE, // 空闲状态
CSV_PARSE_READING, // 文件读取中
CSV_PARSE_PROCESSING, // 数据处理中
CSV_PARSE_RESPONDING // 响应发送中
} eCsvParseState;
typedef struct
{
/* 文件层 */
FILE *pFile; // 文件指针
long lFileOffset; // 当前文件偏移
/* 应用缓存层 */
uint8_t uFileBuf[FILE_READ_BUF_SIZE]; // 文件读取缓冲区
uint16_t uFileBufDataLen; // 有效数据长度
uint16_t uFileBufProcessPos; // 已处理位置
/* 行解析层 */
uint8_t uLineBuf[LINE_PARSE_BUF_SIZE]; // 行解析缓冲区
uint16_t uLineBufPos; // 行缓冲当前位置
uint32_t uCurrentLineNum; // 当前解析行号
/* 通信层 */
eCsvParseState eState; // 状态机状态
uint8_t uUartRxBuf[UART_RX_BUF_SIZE]; // 串口接收缓冲
uint8_t uUartRxPos; // 串口接收位置
uint8_t uUartTxBuf[UART_TX_BUF_SIZE]; // 发送缓冲区
uint16_t uUartTxLen;