#include #include #include #include // 操作系统相关头文件 #ifdef _WIN32 #include #define PATH_SEPARATOR '\\' #else #include #include #define PATH_SEPARATOR '/' #endif #define BUFFER_SIZE 1024 // 平台无关的结构体定义 #pragma pack(1) // MPU传感器数据结构 typedef struct { int16_t ax; // 加速度计 X轴 int16_t ay; // 加速度计 Y轴 int16_t az; // 加速度计 Z轴 int16_t gx; // 陀螺仪 X轴 int16_t gy; // 陀螺仪 Y轴 int16_t gz; // 陀螺仪 Z轴 } sensor_data_t; // 完整的数据记录结构 typedef struct { uint8_t y; // 年(相对值,需要加上2000) uint8_t month; // 月 uint8_t d; // 日 uint8_t h; // 时 uint8_t m; // 分 uint8_t s; // 秒 uint16_t ms; // 毫秒 int16_t deepth; // 深度 sensor_data_t data; // MPU传感器数据 } info_t; #pragma pack() // 平台相关的函数封装 void platform_init(void) { #ifdef _WIN32 // Windows: 设置控制台代码页为UTF-8 SetConsoleOutputCP(65001); #else // Linux: 设置locale为UTF-8 setlocale(LC_ALL, "en_US.UTF-8"); #endif } // 生成输出文件名 char* generate_output_filename(const char* input_file) { size_t len = strlen(input_file); char* output = (char*)malloc(len + 5); // +5 for ".csv\0" if (!output) return NULL; strcpy(output, input_file); // 找到最后一个点的位置 char* dot = strrchr(output, '.'); if (dot != NULL) { strcpy(dot, ".csv"); } else { strcat(output, ".csv"); } return output; } // 检测系统字节序 static uint8_t is_little_endian(void) { uint16_t test = 0x0001; return *(uint8_t *)&test; } // 字节序转换函数 static uint16_t swap_uint16(uint16_t val) { return (val << 8) | (val >> 8); } static int16_t swap_int16(int16_t val) { return (val << 8) | ((val >> 8) & 0xFF); } void decode(char *filename) { uint8_t sys_is_le = is_little_endian(); #ifdef _WIN32 fprintf(stderr, "系统类型: Windows\n"); #else fprintf(stderr, "系统类型: Linux\n"); #endif fprintf(stderr, "系统字节序: %s\n", sys_is_le ? "小端序" : "大端序"); FILE *file = fopen(filename, "rb"); if (!file) { fprintf(stderr, "无法打开文件: %s\n", filename); return; } // 获取文件大小 fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); // 计算记录数量 size_t recordCount = fileSize / sizeof(info_t); // 打印CSV格式的表头 printf("年,月,日,时,分,秒,毫秒,深度,ax,ay,az,gx,gy,gz\n"); // 使用缓冲区读取以提高效率 info_t buffer[BUFFER_SIZE]; size_t records_read; while ((records_read = fread(buffer, sizeof(info_t), BUFFER_SIZE, file)) > 0) { for (size_t i = 0; i < records_read; i++) { // 如果系统是大端序,需要转换所有16位数据 uint16_t ms = buffer[i].ms; int16_t depth = buffer[i].deepth; int16_t ax = buffer[i].data.ax; int16_t ay = buffer[i].data.ay; int16_t az = buffer[i].data.az; int16_t gx = buffer[i].data.gx; int16_t gy = buffer[i].data.gy; int16_t gz = buffer[i].data.gz; if (!sys_is_le) { // 系统是大端序,需要转换 ms = swap_uint16(ms); depth = swap_int16(depth); ax = swap_int16(ax); ay = swap_int16(ay); az = swap_int16(az); gx = swap_int16(gx); gy = swap_int16(gy); gz = swap_int16(gz); } printf("%04d,%02d,%02d,%02d,%02d,%02d,%03d,%04d,%d,%d,%d,%d,%d,%d\n", buffer[i].y + 2000, // 单字节数据不需要转换 buffer[i].month, buffer[i].d, buffer[i].h, buffer[i].m, buffer[i].s, ms, // 使用可能转换过的值 depth, ax, ay, az, gx, gy, gz ); } } fclose(file); fprintf(stderr, "共解析 %zu 条记录\n", recordCount); } void print_usage(const char* program_name) { fprintf(stderr, "用法:\n"); #ifdef _WIN32 fprintf(stderr, "%s -f <文件名> [-o <输出文件名>]\n", program_name); #else fprintf(stderr, "./%s -f <文件名> [-o <输出文件名>]\n", program_name); #endif fprintf(stderr, "选项:\n"); fprintf(stderr, " -f <文件名> 指定输入文件\n"); fprintf(stderr, " -o <文件名> 指定输出文件(可选,默认输出到与输入同名的.csv文件)\n"); fprintf(stderr, " -h 显示帮助信息\n"); fprintf(stderr, "\n示例:\n"); #ifdef _WIN32 fprintf(stderr, "%s -f 20241112.BIN\n", program_name); fprintf(stderr, "%s -f 20241112.BIN -o output.csv\n", program_name); #else fprintf(stderr, "./%s -f 20241112.BIN\n", program_name); fprintf(stderr, "./%s -f 20241112.BIN -o output.csv\n", program_name); #endif } int main(int argc, char *argv[]) { // 平台初始化 platform_init(); char *input_file = NULL; char *output_file = NULL; // 解析命令行参数 for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-h") == 0) { print_usage(argv[0]); return 0; } else if (strcmp(argv[i], "-f") == 0) { if (i + 1 < argc) { input_file = argv[i + 1]; i++; } else { fprintf(stderr, "错误:-f 参数后需要指定文件名\n"); print_usage(argv[0]); return 1; } } else if (strcmp(argv[i], "-o") == 0) { if (i + 1 < argc) { output_file = argv[i + 1]; i++; } else { fprintf(stderr, "错误:-o 参数后需要指定文件名\n"); print_usage(argv[0]); return 1; } } else { fprintf(stderr, "错误:未知参数 %s\n", argv[i]); print_usage(argv[0]); return 1; } } // 检查必需参数 if (input_file == NULL) { fprintf(stderr, "错误:未指定输入文件\n"); print_usage(argv[0]); return 1; } // 如果没有指定输出文件,生成默认的输出文件名 char *auto_output_file = NULL; if (output_file == NULL) { auto_output_file = generate_output_filename(input_file); output_file = auto_output_file; } // 重定向标准输出到文件 if (output_file != NULL) { if (freopen(output_file, "w", stdout) == NULL) { fprintf(stderr, "错误:无法创建输出文件 %s\n", output_file); if (auto_output_file) free(auto_output_file); return 1; } } // 解析文件 decode(input_file); // 清理 if (auto_output_file) { free(auto_output_file); } return 0; }