demo3/decode.c
2024-11-30 10:31:34 +08:00

236 lines
6.7 KiB
C
Raw 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 <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <windows.h>
// 定义缓冲区大小(可以根据实际需求调整)
#define BUFFER_SIZE 1024 // 每次读取1024条记录
// 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;
// 完整的数据记录结构
#pragma pack(1)
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()
// 检测系统字节序
static uint8_t is_little_endian() {
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 print_usage() {
printf("用法:\n");
printf("decode.exe -f <文件名> [-o <输出文件名>]\n");
printf("选项:\n");
printf(" -f <文件名> 指定输入文件\n");
printf(" -o <文件名> 指定输出文件(可选,默认输出到与输入同名的.csv文件\n");
printf(" -h 显示帮助信息\n");
printf("\n示例:\n");
printf("decode.exe -f 20241112.BIN\n");
printf("decode.exe -f 20241112.BIN -o output.csv\n");
}
// 原有的decode函数保持不变
void decode(char *filename) {
FILE *file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "无法打开文件\n");
return;
}
// 检测系统字节序
uint8_t sys_is_le = is_little_endian();
// 显示系统字节序
fprintf(stderr, "系统字节序: %s\n",
sys_is_le ? "小端序" : "大端序");
// 获取文件大小
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
// 计算记录数量
int 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, "共解析 %d 条记录\n", recordCount);
}
// 生成输出文件名
char* generate_output_filename(const char* input_file) {
size_t len = strlen(input_file);
char* output = (char*)malloc(len + 5); // +5 为了容纳 .csv 和结束符
// 复制输入文件名
strcpy(output, input_file);
// 找到最后一个点的位置
char* dot = strrchr(output, '.');
if (dot != NULL) {
// 如果找到点,在点的位置替换后缀
strcpy(dot, ".csv");
} else {
// 如果没有找到点,直接在末尾添加.csv
strcat(output, ".csv");
}
return output;
}
int main(int argc, char *argv[]) {
// 设置控制台输出代码页为 UTF-8
SetConsoleOutputCP(65001);
char *input_file = NULL;
char *output_file = NULL;
// 解析命令行参数
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0) {
print_usage();
return 0;
}
else if (strcmp(argv[i], "-f") == 0) {
if (i + 1 < argc) {
input_file = argv[i + 1];
i++;
} else {
printf("错误:-f 参数后需要指定文件名\n");
print_usage();
return 1;
}
}
else if (strcmp(argv[i], "-o") == 0) {
if (i + 1 < argc) {
output_file = argv[i + 1];
i++;
} else {
printf("错误:-o 参数后需要指定文件名\n");
print_usage();
return 1;
}
}
else {
fprintf(stderr, "错误:未知参数 %s\n", argv[i]);
print_usage();
return 1;
}
}
// 检查必需参数
if (input_file == NULL) {
fprintf(stderr, "错误:未指定输入文件\n");
print_usage();
return 1;
}
// 检查输入文件是否存在
FILE *file = fopen(input_file, "rb");
if (!file) {
printf("错误:无法打开输入文件 %s\n", input_file);
return 1;
}
fclose(file);
// 如果没有指定输出文件,生成默认的输出文件名
char *auto_output_file = NULL;
if (output_file == NULL) {
auto_output_file = generate_output_filename(input_file);
output_file = auto_output_file;
}
// 重定向标准输出到文件
if (freopen(output_file, "w", stdout) == NULL) {
printf("错误:无法创建输出文件 %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;
}