Files
LaserTracing/docs/项目架构与工作流程分析.md
T

261 lines
13 KiB
Markdown
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.
# 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` 配置、天线开关状态。