demo3/decode.c
2024-11-30 11:06:18 +08:00

260 lines
7.2 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
// 操作系统相关头文件
#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)
// 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;
}