# 配置管理功能说明

## 概述
将数据输出模式配置从编译时的 `#define` 改为运行时可配置，配置存储在SD卡文件中，系统启动时自动加载。

## 配置项

### 1. UART输出使能 (uart_output_enabled)
- **功能**: 控制是否通过串口(RS485)发送数据
- **默认值**: 1 (启用)
- **取值**: 0=禁用, 1=启用

### 2. 存储使能 (storage_enabled)
- **功能**: 控制是否将数据存储到SD卡
- **默认值**: 0 (禁用)
- **取值**: 0=禁用, 1=启用

## 配置文件

### 文件路径
```
0:/CONFIG.TXT
```

### 文件格式
```
UART=1
STORAGE=0
SESSION=0
VERSION=65536
```

**说明**:
- `UART`: 串口输出使能状态 (0或1)
- `STORAGE`: SD卡存储使能状态 (0或1)
- `SESSION`: 会话序号 (用于数据存储文件夹命名)
- `VERSION`: 配置版本号 (用于验证配置兼容性)

## 使用方法

### 1. 初始化配置管理器
```c
// 在main()函数中初始化
Config_Init();  // 设置默认配置
```

### 2. 加载配置
```c
// 在文件系统挂载后加载配置
if (Config_Load() == HAL_OK) {
    // 配置加载成功
} else {
    // 配置加载失败，使用默认值
}
```

### 3. 读取配置
```c
// 检查串口输出是否启用
if (Config_IsUartOutputEnabled()) {
    RS485_SendData(data, size);
}

// 检查存储是否启用
if (Config_IsStorageEnabled()) {
    DataStorage_WriteData(&storage, &packet);
}
```

### 4. 修改配置
```c
// 修改串口输出设置
Config_SetUartOutput(1);  // 启用
Config_SetUartOutput(0);  // 禁用

// 修改存储设置
Config_SetStorage(1);     // 启用
Config_SetStorage(0);     // 禁用

// 保存配置到SD卡
Config_Save();
```

## 配置文件管理

### 创建配置文件
如果SD卡中不存在配置文件，系统会在首次启动时自动创建，使用默认配置值。

### 修改配置文件
可以通过以下方式修改配置：

1. **通过USB连接修改**:
   - 将设备连接到PC
   - 打开SD卡中的 `CONFIG.TXT` 文件
   - 修改配置值
   - 保存文件
   - 断开USB，重启设备

2. **通过代码修改**:
   ```c
   Config_SetUartOutput(1);
   Config_SetStorage(1);
   Config_Save();  // 保存到SD卡
   ```

### 恢复默认配置
```c
Config_SetDefaults();  // 恢复默认值
Config_Save();         // 保存到SD卡
```

## 配置验证

配置管理器包含以下验证机制：

1. **版本检查**: 确保配置文件版本与当前软件兼容
2. **值范围检查**: 确保配置值在有效范围内 (0或1)
3. **校验和验证**: 检测配置数据完整性

如果验证失败，系统将自动使用默认配置。

## 与原有代码的对比

### 原有方式（编译时配置）
```c
#define DATA_OUTPUT_MODE_UART       1
#define DATA_OUTPUT_MODE_STORAGE    0

#if DATA_OUTPUT_MODE_UART
    RS485_SendData(data, size);
#endif

#if DATA_OUTPUT_MODE_STORAGE
    DataStorage_WriteData(&storage, &packet);
#endif
```

### 新方式（运行时配置）
```c
// 配置从SD卡加载
if (Config_IsUartOutputEnabled()) {
    RS485_SendData(data, size);
}

if (Config_IsStorageEnabled()) {
    DataStorage_WriteData(&storage, &packet);
}
```

## 优势

1. **灵活性**: 无需重新编译即可更改配置
2. **便捷性**: 通过修改SD卡文件即可调整系统行为
3. **可维护性**: 配置集中管理，易于维护
4. **可扩展性**: 易于添加新的配置项

## 注意事项

1. **文件系统依赖**: 配置加载需要SD卡文件系统正常工作
2. **启动顺序**: 必须在文件系统挂载后才能加载配置
3. **默认配置**: 如果配置文件不存在或损坏，系统使用默认配置
4. **性能影响**: 运行时检查比编译时宏略慢，但影响可忽略

## 文件修改清单

1. **User/config_manager.h** - 配置管理器头文件
2. **User/config_manager.c** - 配置管理器实现
3. **Core/Src/main.c** - 集成配置管理器，替换编译时宏

## 配置示例

### 示例1: 仅串口输出
```
UART=1
STORAGE=0
SESSION=0
VERSION=65536
```

### 示例2: 仅SD卡存储
```
UART=0
STORAGE=1
SESSION=5
VERSION=65536
```

### 示例3: 同时启用
```
UART=1
STORAGE=1
SESSION=10
VERSION=65536
```

### 示例4: 全部禁用
```
UART=0
STORAGE=0
SESSION=0
VERSION=65536
```

## 会话序号管理

### 会话序号的作用
会话序号用于为每次数据采集创建唯一的文件夹。每次系统启动并开始数据存储时，会话序号会自动递增，生成类似 `SESSION_000001`、`SESSION_000002` 的文件夹名称。

### 会话序号函数
```c
// 获取当前会话序号
uint32_t session_num = Config_GetSessionNumber();

// 设置会话序号
Config_SetSessionNumber(100);

// 递增会话序号并返回新值
uint32_t new_session = Config_IncrementSessionNumber();
```

### 注意事项
- 会话序号在 [`DataStorage_CreateSessionFolder()`](User/data_storage.c:413) 中自动递增
- 配置文件统一管理，替代了原来的 `PARAM.TXT` 文件
- 会话序号会随配置一起保存到 `CONFIG.TXT`
