demo3/decode.c

260 lines
7.2 KiB
C
Raw Normal View History

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;
}