2024-11-30 02:15:30 +00:00
|
|
|
|
#include <stdio.h>
|
2024-11-30 03:06:18 +00:00
|
|
|
|
#include <stdint.h>
|
2024-11-30 02:15:30 +00:00
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
2024-11-30 03:06:18 +00:00
|
|
|
|
// 操作系统相关头文件
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#define PATH_SEPARATOR '\\'
|
|
|
|
|
#else
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <locale.h>
|
|
|
|
|
#define PATH_SEPARATOR '/'
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 1024
|
|
|
|
|
|
|
|
|
|
// 平台无关的结构体定义
|
|
|
|
|
#pragma pack(1)
|
2024-11-30 02:15:30 +00:00
|
|
|
|
// 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()
|
|
|
|
|
|
2024-11-30 03:06:18 +00:00
|
|
|
|
// 平台相关的函数封装
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-30 02:31:34 +00:00
|
|
|
|
// 检测系统字节序
|
2024-11-30 03:06:18 +00:00
|
|
|
|
static uint8_t is_little_endian(void) {
|
2024-11-30 02:31:34 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-30 02:15:30 +00:00
|
|
|
|
void decode(char *filename) {
|
2024-11-30 03:06:18 +00:00
|
|
|
|
uint8_t sys_is_le = is_little_endian();
|
2024-11-30 02:31:34 +00:00
|
|
|
|
|
2024-11-30 03:06:18 +00:00
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
fprintf(stderr, "系统类型: Windows\n");
|
|
|
|
|
#else
|
|
|
|
|
fprintf(stderr, "系统类型: Linux\n");
|
|
|
|
|
#endif
|
|
|
|
|
fprintf(stderr, "系统字节序: %s\n", sys_is_le ? "小端序" : "大端序");
|
|
|
|
|
|
2024-11-30 02:15:30 +00:00
|
|
|
|
FILE *file = fopen(filename, "rb");
|
|
|
|
|
if (!file) {
|
2024-11-30 03:06:18 +00:00
|
|
|
|
fprintf(stderr, "无法打开文件: %s\n", filename);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-30 03:06:18 +00:00
|
|
|
|
|
2024-11-30 02:15:30 +00:00
|
|
|
|
// 获取文件大小
|
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
|
|
|
long fileSize = ftell(file);
|
|
|
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
// 计算记录数量
|
2024-11-30 03:06:18 +00:00
|
|
|
|
size_t recordCount = fileSize / sizeof(info_t);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
|
|
|
|
|
// 打印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++) {
|
2024-11-30 02:31:34 +00:00
|
|
|
|
// 如果系统是大端序,需要转换所有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);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-30 02:15:30 +00:00
|
|
|
|
printf("%04d,%02d,%02d,%02d,%02d,%02d,%03d,%04d,%d,%d,%d,%d,%d,%d\n",
|
2024-11-30 02:31:34 +00:00
|
|
|
|
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
|
2024-11-30 02:15:30 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
|
|
2024-11-30 03:06:18 +00:00
|
|
|
|
fprintf(stderr, "共解析 %zu 条记录\n", recordCount);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-30 03:06:18 +00:00
|
|
|
|
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
|
2024-11-30 02:15:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
2024-11-30 03:06:18 +00:00
|
|
|
|
// 平台初始化
|
|
|
|
|
platform_init();
|
|
|
|
|
|
2024-11-30 02:15:30 +00:00
|
|
|
|
char *input_file = NULL;
|
|
|
|
|
char *output_file = NULL;
|
|
|
|
|
|
|
|
|
|
// 解析命令行参数
|
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
|
if (strcmp(argv[i], "-h") == 0) {
|
2024-11-30 03:06:18 +00:00
|
|
|
|
print_usage(argv[0]);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp(argv[i], "-f") == 0) {
|
|
|
|
|
if (i + 1 < argc) {
|
|
|
|
|
input_file = argv[i + 1];
|
|
|
|
|
i++;
|
|
|
|
|
} else {
|
2024-11-30 03:06:18 +00:00
|
|
|
|
fprintf(stderr, "错误:-f 参数后需要指定文件名\n");
|
|
|
|
|
print_usage(argv[0]);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp(argv[i], "-o") == 0) {
|
|
|
|
|
if (i + 1 < argc) {
|
|
|
|
|
output_file = argv[i + 1];
|
|
|
|
|
i++;
|
|
|
|
|
} else {
|
2024-11-30 03:06:18 +00:00
|
|
|
|
fprintf(stderr, "错误:-o 参数后需要指定文件名\n");
|
|
|
|
|
print_usage(argv[0]);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
fprintf(stderr, "错误:未知参数 %s\n", argv[i]);
|
2024-11-30 03:06:18 +00:00
|
|
|
|
print_usage(argv[0]);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查必需参数
|
|
|
|
|
if (input_file == NULL) {
|
|
|
|
|
fprintf(stderr, "错误:未指定输入文件\n");
|
2024-11-30 03:06:18 +00:00
|
|
|
|
print_usage(argv[0]);
|
2024-11-30 02:15:30 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果没有指定输出文件,生成默认的输出文件名
|
|
|
|
|
char *auto_output_file = NULL;
|
|
|
|
|
if (output_file == NULL) {
|
|
|
|
|
auto_output_file = generate_output_filename(input_file);
|
|
|
|
|
output_file = auto_output_file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重定向标准输出到文件
|
2024-11-30 03:06:18 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2024-11-30 02:15:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析文件
|
|
|
|
|
decode(input_file);
|
|
|
|
|
|
|
|
|
|
// 清理
|
|
|
|
|
if (auto_output_file) {
|
|
|
|
|
free(auto_output_file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|