docs: 新增项目架构与工作流程分析文档

This commit is contained in:
2026-09-01 19:06:16 +08:00
parent f239690002
commit c417d124a0
+261
View File
@@ -0,0 +1,261 @@
# LaserTracing 项目架构与工作流程分析
## 1. 项目概述
LaserTracing(激光示踪)是基于华大 HC32L170ARM Cortex-M0+)超低功耗 MCU 的嵌入式传感器项目。设备通过 LoRa(SX1276)无线通信接入网关,采集三维姿态角(俯仰/横滚/偏航)并定时上报,同时支持激光控制、低功耗休眠、FPO 全功率时间段等特性。
### 1.1 硬件组成
| 模块 | 型号/接口 | 用途 |
|------|-----------|------|
| MCU | HC32L170 | 主控,Cortex-M0+ |
| LoRa | SX1276 (SPI0) | 与网关无线通信 |
| 加速度计 | LSM6DSL (I2C0) | 采集加速度/陀螺仪 |
| 地磁 | MMC5983 (I2C0) | 采集磁场 |
| 激光 | LASER1~3 (GPIO) | 激光开关控制 |
| ADC | ADC (EXCH4) | 电池电压采样 |
| 调试口 | UART/RS485 | 调试命令交互 |
### 1.2 软件版本
- 软件版本: `SOFTWARE_VERSION = 12`
- 硬件版本: `HARDWARE_VERSION = 11`
## 2. 目录结构
```
LaserTracing/
├── MDK/ # Keil 工程文件 (uvprojx/uvoptx/RTE)
├── Module/ # 功能模块
│ ├── Imu/ # IMU 姿态解算上层
│ ├── LORA/ # SX1276 LoRa 驱动 (sx127x.c/h)
│ ├── LaserTracing_Debug/ # 调试命令模块 (UartDebug.c/h)
│ ├── MahonyAHRS/ # 姿态解算算法库
│ ├── lsm6dsl/ # LSM6DSL 驱动 (含寄存器层)
│ └── mmc5983/ # MMC5983 驱动
├── driver/ # HC32L170 官方外设驱动库 (inc/src)
├── mcu/ # 芯片支持包 (启动文件、FlashLoader)
├── source/
│ ├── inc/ # 项目头文件
│ │ ├── main.h # 应用结构体/状态机/全局声明
│ │ ├── bsp.h # 板级定义/参数结构/外设宏
│ │ ├── SGCP.h # 通信协议定义
│ │ ├── Algorithm.h # 算法接口
│ │ ├── Update.h # 升级接口
│ │ └── UartDebug.h # 调试接口
│ └── src/
│ ├── main.c # 主流程/状态机/数据采集
│ ├── bsp.c # 板级初始化/中断处理/外设封装
│ ├── SGCP.c # 通信协议栈 (网关交互)
│ ├── Algorithm.c # 工具函数/辅助算法
│ └── Update.c # 固件升级逻辑
└── docs/ # 本文档
```
## 3. 核心架构分层
### 3.1 分层结构
```
┌─────────────────────────────────────────────┐
│ 应用层 (main.c) │
│ - AppInit/主循环/状态机/数据采集与处理 │
├─────────────────────────────────────────────┤
│ 协议层 (SGCP.c) │
│ - 注册/上报/配置/激光/信号 帧处理与状态机 │
├─────────────────────────────────────────────┤
│ 模块层 (Module/) │
│ - LoRa/IMU/AHRS/传感器/调试 各功能模块 │
├─────────────────────────────────────────────┤
│ 驱动层 (driver/ + bsp.c) │
│ - HC32L170 外设驱动 + 板级封装 │
└─────────────────────────────────────────────┘
```
### 3.2 关键全局对象
- `App` (`AppDetect_t`):应用状态、传感器数据、姿态结果、配置参数、各类标志与计数器。
- `SGCP` (`SGCP_t`):通信协议状态、网关/设备 MAC、接收缓冲区、指令状态机标志。
- `LocalMAC` / `GatewayMAC`:本机 6 字节 MAC 与网关 MAC。
- `LocalDataPack`:本机待上报的打包数据。
## 4. 工作流程分析
### 4.1 系统启动流程 (main)
```
main()
├─ BspInit() # 时钟、GPIO、外设、中断初始化
├─ delay_ms(3000) # 上电等待
├─ AppInit() # 读参数、校验恢复默认、初始化 RTC/LPTimer/LoRa/传感器
├─ 打印版本信息
└─ while(1) 主循环
├─ ADCLoopHandler() # 电池电压采样
├─ FeedDogHandler() # 看门狗喂狗
├─ DebugLoopHandler() # 调试命令处理
├─ Lsm6dslLoopHandler() # 加速度数据处理
├─ MMC5983LoopHandler() # 地磁数据处理
├─ ReadDataLoopHandler() # 数据采集状态机
├─ GwRevLoopHandler() # 网关收发状态机
├─ InRevLoopHandler() # 内部指令处理
└─ AppLoopHandler() # 应用状态机
```
### 4.2 时基中断与回调
| 中断 | 功能 |
|------|------|
| SysTick_CallBack (1ms) | 调用各 1mSRoutine 递减计数器 |
| RtcIRQHander (30s) | 系统定时重启、定时采集触发、周期上报、紧急上报 |
| LPTimer0IRQHander | 注册/上传重试定时器 |
| PortB_IRQHandler | LoRa DIO0(发送完成/接收完成) |
| PortC_IRQHandler | 加速度 INT1 / 地磁 INT 回调 |
### 4.3 应用状态机 (AppLoopHandler / APP_STATUS_*)
```
APP_STATUS_SLEEP → APP_STATUS_ON → APP_STATUS_ACTION
┌─────────────────────────────────┼───────────────────────────────┐
▼ ▼ ▼
APP_STATUS_WAIT_LOGIN (数据采集) APP_STATUS_WAIT_UPLOAD
│ 注册成功 │ 采集完成(UpdateOk) │ 上传完成/超时
└───────▶ APP_STATUS_ACTION └───────▶ 触发上传 └──────▶ ACTION
```
关键转移条件(`AppLoopHandler` 中按优先级判断):
1. `InStatus != IDLE` → 等待内部指令完成
2. `LoginOk == false && LoginFlag == true && GWStatus == IDLE` → 发起注册
3. `TimingAcquisition == true && RDStatus == IDLE` → 启动传感器采集
4. `LoginOk == true && UploadFlag == true && GWStatus == IDLE && UpdateOk == true` → 上传数据
5. `LaserOnOff == true && LaserTimerCount == 0` → 激光状态处理
6. 全部空闲且 `IsFullPowerTime() == false` → 进入休眠 (`APP_STATUS_OFF`)
### 4.4 数据采集状态机 (ReadDataLoopHandler / READDATA_STATUS_*)
```
READDATA_STATUS_IDLE
└─(TimingAcquisition=true)─▶ READDATA_STATUS_UPDAING
(启动 LSM6DSL + MMC5983,置 ReadData1mSDelayCnt=2000)
└─▶ READDATA_STATUS_WAIT_UPDAING
(等待中断回调置 MagRead_EndFlag / AccRead_EndFlag 或 2s 超时)
└─▶ READDATA_STATUS_DATA_HANDLE
(IMU_Update 解算 → 存 ConvertedData → 拷入 LocalDataPack)
└─▶ READDATA_STATUS_IDLE (置 UpdateOk=true)
```
若任一传感器超时(未收到中断),`UpdateOk` 保持 false,本周期数据不用于上报。
### 4.5 注册与数据上报时序
1. 上电后 `LPTimer0_ON(50)`5s)后 `LoginFlag=true`
2. `APP_STATUS_ACTION` 检测到注册条件 → `GW_STATUS_LOGIN``ToGWDevLogin()` 发送注册帧(Cmd=0x00)。
3. 网关回应注册 → `GWRevHandler``LoginOk`、保存 `GatewayMAC``GW_STATUS_WAIT_LOGIN``LoginMess``TimingAcquisition=true`
4. `APP_STATUS_WAIT_LOGIN``UploadFlag=true` 并触发采集。
5. 采集完成 `UpdateOk=true``APP_STATUS_ACTION``GW_STATUS_UPLOAD_SENSOR``ToGWReadDataRes()` 发送数据帧(Cmd=0x02)。
6. `GW_STATUS_WAIT_UPLOAD` 等网关回应(2s 超时)。收到回应 `UploadOk=true` → 上报成功;超时则 `UploadMess=true`,由 `APP_STATUS_WAIT_UPLOAD` 计数重试,3 次失败后重新注册。
### 4.6 协议帧格式 (SGCP)
网关↔设备固定帧(16 字节头):
```
| Header(1) | GWAddr(6) | MDAddr(6) | Cmd(1) | PayloadLen(2) | Payload(N) | CRC16(2) |
```
命令字(网关→设备):
| Cmd | 含义 |
|-----|------|
| 0x00 | 设备注册 (GWTOMD_CMD_LOGIN) |
| 0x01 | 校准 (GWTOMD_CMD_CALI) |
| 0x02 | 读取/上传数据 (GWTOMD_CMD_READ_UPLOAD_SENSOR) |
| 0x05 | 设置采集时间间隔 (GWTOMD_CMD_SET_COL_TIME) |
| 0x06 | 时间同步 (GWTOMD_CMD_SYNC_TIME) |
| 0x08 | 打开/关闭激光 (GWTOMD_CMD_SET_LASER) |
| 0x09 | 信号质量查询 (GWTOMD_CMD_SIGNAL) |
| 0x0A | 设置全功率运行时间段 (GWTOMD_CMD_SET_FPO) |
`LayoutPara_t` 参数(网关下发,10 字节 + 时间戳):CollectTime / ReportInterval / ERInterval / ERTime / FPOTimeStart / FPOTime / TimeStamp。
### 4.7 网关状态机 (GwRevLoopHandler / GW_STATUS_*)
```
GW_STATUS_IDLE
├─▶ LOGIN → WAIT_LOGIN → IDLE # 注册流程
├─▶ CALI → 校准回应 # 校准
├─▶ SET_COL_TIME → 采集间隔回应
├─▶ SET_FPO → 全功率时间段回应 (0x0A)
├─▶ SYNC_TIME → 时间同步
├─▶ UPLOAD_SENSOR → WAIT_UPLOAD # 上报流程
├─▶ LASER_STARES → 激光状态回应
└─▶ SIGNAL → WAIT_SIGNAL → 信号质量
```
### 4.8 低功耗与休眠
- 空闲时判断:`RDStatus==IDLE && GWStatus==IDLE && InStatus==IDLE && !TimingAcquisition && 各延时==0 && !LaserOnOff && !AttTestMode && !IsFullPowerTime()``APP_STATUS_OFF` → 关闭 LED → `APP_STATUS_SLEEP`
- `APP_STATUS_SLEEP` 中调用 `EnterDeepSleep()` 深睡眠,`WakeUpInit()` 唤醒后回 `APP_STATUS_ON`
- **FPO 全功率时间段**:由 `IsFullPowerTime()` 判断当前本地小时是否落在 `[FPOTimeStart, FPOTimeStart+FPOTime)` 区间内(支持跨天、0 时长表示关闭),在 FPO 时段内不进入休眠。FPOTime 默认 0,`TimeGet` 从 RTC 读取当前小时(本地时间)。
### 4.9 激光控制
- 网关下发 0x08 指令置 `SGCP.LaserOnOff``LaserTimerMinutes`(默认 **1 分钟**)决定自动关闭时长。
- `GW_STATUS_LASER_STARES` 中执行 `LASER1_ON/OFF()` 并回应网关。
- RTC 30s 中断中 `LaserTimerCount--`,归零后再次进入 `GW_STATUS_LASER_STARES` 执行关闭。
## 5. 通信模式配置
| 宏 | 值 | 说明 |
|----|----|------|
| `WORK_MODE` | 1 | 0=查询模式,1=上报模式(低功耗) |
| `SGCP_SELECT` | 1 | 0=主+子多设备,1=单主设备(当前),2=单子设备 |
| `USE_VBAT_AD` | 1 | 电池电压采样开关 |
| `USE_WDT` | 1 | 看门狗开关 |
| `USE_DEBUG` | 1 | 调试命令开关 |
| `USE_BOOTLOADER` | 0 | BootLoader 升级开关 |
## 6. LoRa 信道配置
中心频率范围 **470100000 ~ 492600000 Hz**,步进 **500000 Hz**,共 **46 个信道**CH0~CH45):
- CH0 = 470100000CH1 = 470600000...CH45 = 492600000。
- 默认 `FREQ_CENT = CH0`;信道切换上限 `LoraSetChannel` 允许 0~45。
- 频率范围校验(`LoraSetFreqCent` / AppInit):410000000 ~ 525000000,覆盖全部信道。
- 可通过调试命令 `lora ch <0~45>` 配置信道。
## 7. 调试命令 (UartDebug)
| 命令 | 说明 |
|------|------|
| `reg` | 手动触发注册 |
| `para` | 打印当前配置参数(含 FPO、激光状态) |
| `lpcfg CI RI EI ET` | 配置低功耗采集/上报参数 |
| `fpocfg Start Dur` | 配置全功率运行时间段(配置后自动向网关发送 0x0A 通知) |
| `lora ch/pw/bw/sf/ec/rp/fc/o` | 配置 LoRa 参数 |
| `laser` | 激光控制与定时配置 |
| `rs485` / `dch` | RS485 通道控制 / 调试通道切换 |
| `res` | 恢复出厂设置 |
| `dbg` | 调试开关控制 |
## 8. 关键文件与职责对照
| 文件 | 主要职责 |
|------|----------|
| `source/src/main.c` | 主流程、应用状态机、数据采集状态机、FPO 判断、中断回调 |
| `source/src/SGCP.c` | 协议栈:帧组包/解析、网关状态机、注册/上报/配置/激光/信号处理 |
| `source/src/bsp.c` | 板级初始化、外设封装、中断处理、RTC/TimeGet/低功耗 |
| `source/inc/SGCP.h` | 协议常量、帧结构、命令字、状态机、设备数据定义 |
| `source/inc/bsp.h` | 板级宏、参数结构(LayoutPara_t 等)、外设引脚定义 |
| `source/inc/main.h` | 应用结构体、状态机枚举、宏定义 |
| `Module/LORA/sx127x.c` | LoRa 收发、信道/频率/功率配置 |
| `Module/LaserTracing_Debug/UartDebug.c` | 调试命令解析执行 |
| `Module/lsm6dsl` / `mmc5983` | 传感器驱动与数据回调 |
| `Module/MahonyAHRS` / `Imu` | 姿态解算 |
## 9. 典型问题排查路径
- **注册失败/超时**:查 `GW_STATUS_WAIT_LOGIN` 超时日志、网关 MAC 是否保存、LoRa 接收是否正常。
- **上传超时**:查 `GW_STATUS_WAIT_UPLOAD` 日志、`LocalDataPack` 是否全 0`is_all_byte` 检查)、`UpdateOk` 是否被置位、传感器采集是否超时。
- **无法休眠**:查 `IsFullPowerTime()` 时段判断、`InStatus/GWStatus/RDStatus` 是否处于非 IDLE、各类延时计数是否清零。
- **LoRa 通信异常**:核对信道频率范围(470.1~492.6MHz)与网关是否一致、`FREQ_CENT`/`FreqCent` 配置、天线开关状态。