Compare commits

...

4 Commits

2 changed files with 1599 additions and 23 deletions

View File

@@ -114,34 +114,88 @@ typedef struct {
## 4. 软件层级架构与核心代码框架 ## 4. 软件层级架构与核心代码框架
软件系统采用 **非阻塞**三层级模块化架构设计: 软件系统采用 **分层依赖、事件驱动、非阻塞** 的模块化架构设计。其层级结构与核心依赖关系如下
### 4.1 系统软件架构分层 (三层架构设计)
为了清晰呈现系统的软硬件隔离层次,手环系统采用单向依赖的层级架构:
```mermaid ```mermaid
graph TD graph TD
subgraph Layer3 ["应用层 (APP)"] subgraph APP ["应用逻辑层 (APP Layer)"]
MainScheduler[主循环轮询 & 喂狗] MainScheduler["主循环调度 (main.c)"]
SysStateMachine[SystemState 业务状态机] SysStateMachine["业务状态机 (sys_state)"]
SoftRTC[软件 RTC 计时器]
end end
subgraph Layer2 ["外设驱动层 (DRV)"] subgraph DRV ["外设驱动层 (DRV Layer)"]
AMOLED[RM69310 AMOLED 屏幕绘制] KEY["KEY 驱动"]
RF[LR690L 编解码 & 过滤 0x08 SOS 信号] RF["RF 驱动"]
KEY[按键消抖 & 长按长计时] AMOLED["AMOLED 屏刷"]
PM[低功耗休眠与唤醒] PM["PM 功耗驱动"]
LED[WS2812B 级联双彩灯时序] LED["LED 彩灯驱动"]
MOTOR[振动马达脉冲时序] MOTOR["马达震动驱动"]
end end
subgraph Layer1 ["硬件抽象与时基层 (HW)"] subgraph HW ["硬件抽象与时基层 (HW Layer)"]
Timer1["Timer 1 中断 (1ms 滴答)"] Timer1["Timer 1 中断时基"]
ADC[12位电压采集] GPIO["GPIO / ADC / IAP Flash"]
Flash[IAP 读写]
GPIO[数字 I/O 与电平中断]
end end
Layer1 --> Layer2
Layer2 --> Layer3 HW ===>|驱动时基与中断沿| DRV
DRV ===>|提供抽象API与事件缓冲区| APP
APP ===>|调度外设控制指令| DRV
``` ```
### 4.1 核心主程序调度框架 (main.c) ### 4.2 输入事件采集与流转链条 (Input Event Dataflow)
展示按键与无线接收信号从物理引脚触发,经过驱动消抖/解码,进入软件事件缓冲区,并最终被主循环及状态机消费的完整依赖链路:
```mermaid
graph LR
%% 输入物理源 -> 驱动解码 -> 软件缓冲区 -> 状态机消费
Pin_Key["物理按键 P2.0-P3.7"] -->|10ms 定时扫描| KEY["KEY 扫描与消抖"]
KEY -->|判定按键事件| Buf_Key["key_event_buf (环形事件队列)"]
Buf_Key -->|主循环读取并清除| Scheduler["主循环 (main.c)"]
Pin_RF["433MHz 载波沿信号"] -->|INT2 中断触发| RF["RF 自适应解调解码"]
RF -->|解码合法 RFEvent| Scheduler
Scheduler -->|分发有效事件| StateMachine["业务状态机 (SysState)"]
```
### 4.3 控制输出与外设执行链路 (Output Control Flow)
展示业务状态机跳转后,如何通过驱动层向底层硬件引脚输出电平信号,以驱动显示、声光报警、马达振动及电源 PMIC 切断:
```mermaid
graph LR
%% 状态机 -> 外设执行接口 -> 物理引脚拉低/高
StateMachine["业务状态机 (SysState)"] -->|Redraw=1 重绘页面| AMOLED["Truly RM69310 绘制"]
StateMachine -->|防区警示闪烁| LED["WS2812B 彩灯控制"]
StateMachine -->|特定防区震动模式| MOTOR["马达时序控制"]
StateMachine -->|无操作 10s 超时休眠| PM["PM 功耗与电源断电"]
AMOLED -->|SPI 引脚输出| Pin_OLED["OLED 屏幕 (Pin 9-14)"]
LED -->|P2.6 单线时序| Pin_LED["RGB 灯珠 (Pin 27)"]
MOTOR -->|P2.4 PWM 电平| Pin_Mot["马达驱动 (Pin 25)"]
PM -->|P2.7 SHUT 拉低| Pin_PMIC["SGM3833 PMIC (Pin 28)"]
```
### 4.4 架构设计与依赖原则说明
1. **单向依赖原则**
* **APP 层**仅依赖于 **DRV 层**提供的高级抽象接口(例如 `LED_Set_Color``Motor_Start_Pattern`)和 **HW 层**的数据库读写。**严禁**在 APP 层直接写入具体 IO 寄存器。
* **DRV 层**调用 **HW 层**提供的基础时基与 GPIO 端口函数,不保存任何系统级别的状态变量(`current_state` 等)。
* **HW 层**为最底层,除触发中断服务子程序 (ISR) 外,不依赖任何上层逻辑。
2. **事件驱动与非阻塞机制**
* **按键事件缓冲机制**`KEY` 驱动在 Timer1 中断中进行每 10ms 的定时扫描消抖。识别到有效按键动作后,将其转换为 `KeyEvent` 并压入内部的 **环形事件队列**。主循环通过轮询读出该事件,避免了在按键按下时产生任何 `while` 等待导致系统挂起。
* **马达与彩灯的异步时序设计**`MOTOR``LED` 的报警波形(如:长震、间歇闪烁)均采用在 1ms 中断中自动扣减计数器的方式实现。APP 层发出启动指令后立即返回,由硬件中断负责底层的波形电平跳转,保证了射频解码及按键响应不会因为声光报警动作而产生卡顿。
3. **电源控制与低功耗恢复链条**
* 休眠决策完全由主循环内的 `inactivity_timer` 进行倒计时判定。
* 进入休眠前,由 `PM` 驱动断开 `SGM3833` 电源以彻底消除 AMOLED 的暗漏电流。
* 唤醒时,由 GPIO 的电平沿变化触发中断,唤醒 CPU 后由 `PM` 优先执行 **“上电 -> 强延时 50ms 避开浪涌 -> 屏幕控制器重初始化”** 的安全恢复时序,防止未稳定电网下的写屏导致屏幕损坏或花屏。
### 4.5 核心主程序调度框架 (main.c)
主程序采用完全解耦的时间片轮询加事件触发的非阻塞循环结构: 主程序采用完全解耦的时间片轮询加事件触发的非阻塞循环结构:
@@ -243,7 +297,7 @@ void main(void) {
```mermaid ```mermaid
flowchart TD flowchart TD
%% 硬件输入事件 %% 硬件输入事件
PinKey[物理按键按下 / 下降沿] -->|P0.1-P0.5 端口中断| ISR_Port0[Port0 中断 ISR] PinKey[物理按键按下 / 下降沿] -->|P2.0-P3.7 端口中断| ISR_Port0[GPIO 中断 ISR]
Carrier[433MHz 射频载波信号] -->|INT2 中断| ISR_INT2[INT2 唤醒中断 ISR] Carrier[433MHz 射频载波信号] -->|INT2 中断| ISR_INT2[INT2 唤醒中断 ISR]
%% 中断服务层 (ISR) %% 中断服务层 (ISR)
@@ -282,11 +336,11 @@ flowchart TD
| 事件名称 | 输入源 (触发条件与参数) | 状态机判定逻辑 (当前状态与条件) | 输出结果 & 动作执行 (显示、灯效、马达与无线) | | 事件名称 | 输入源 (触发条件与参数) | 状态机判定逻辑 (当前状态与条件) | 输出结果 & 动作执行 (显示、灯效、马达与无线) |
| :--- | :--- | :--- | :--- | | :--- | :--- | :--- | :--- |
| **按键操作事件**<br>`KEY_EVENT` | **源**P0.1~P0.5 下降沿中断。<br>**参数**`KEY_UP``KEY_DOWN``KEY_CONFIRM` (短按/长按)。 | **当前状态**`STATE_CLOCK` / `STATE_MENU` 等。<br>**条件**:在待机下长按确认键 3 秒进入菜单;在菜单下短按 ▲/▼ 键翻页。 | 1. **显示**:置 `Redraw = 1`LCD 刷新切换对应页面;<br>2. **触觉**:发出 50ms 极短振动作按键反馈。 | | **按键操作事件**<br>`KEY_EVENT` | **源**P2.0~P3.7 下降沿中断。<br>**参数**`KEY_UP``KEY_DOWN``KEY_CONFIRM` (短按/长按)。 | **当前状态**`STATE_CLOCK` / `STATE_MENU` 等。<br>**条件**:在待机下长按确认键 3 秒进入菜单;在菜单下短按 ▲/▼ 键翻页。 | 1. **显示**:置 `Redraw = 1`LCD 刷新切换对应页面;<br>2. **触觉**:发出 50ms 极短振动作按键反馈。 |
| **主动求救事件**<br>`SOS_ACTIVE_EVENT` | **源**:上部任意 SOS 按键按下(短按或长按)。 | **当前状态**:除已报警外的任意业务状态。<br>**条件**:无视当前状态,拥有最高抢占优先级。 | 1. **状态**:切入 `STATE_SOS_EMITTED`<br>2. **无线**:通过 LR690L 周期性2s发射手环 Factory ID 及 `0x08` (SOS) 数据包;<br>3. **显示**LCD 闪烁呈现超大警灯与分行 `SOS EMIS` 字样;<br>4. **灯效**WS2812B 红色高速交替闪烁50ms周期<br>5. **马达**:持续间歇长振(振 1000ms停 200ms。 | | **主动求救事件**<br>`SOS_ACTIVE_EVENT` | **源**:上部任意 SOS 按键按下(短按或长按)。 | **当前状态**:除已报警外的任意业务状态。<br>**条件**:无视当前状态,拥有最高抢占优先级。 | 1. **状态**:切入 `STATE_SOS_EMITTED`<br>2. **无线**:通过 LR690L 周期性2s发射手环 Factory ID 及 `0x08` (SOS) 数据包;<br>3. **显示**LCD 闪烁呈现超大警灯与分行 `SOS EMIS` 字样;<br>4. **灯效**WS2812B 红色高速交替闪烁50ms周期<br>5. **马达**:持续间歇长振(振 1000ms停 200ms。 |
| **无线对码捕获事件**<br>`RF_PAIR_RECV_EVENT` | **源**LR690L 接收 433MHz 对码载波包。<br>**参数**24-bit 物理地址 + 4-bit 传感器类型数据码。 | **当前状态**`STATE_PAIR_SEARCH` (搜索对码中)。<br>**条件**:捕获到合法 EV1527 帧。 | 1. **状态**:切换至 `STATE_PAIR_CONFIRM` (确认微调)<br>2. **显示**:只读显示自动识别的传感器名称(如 `PORTE`)、大图标,以及超大 `[ 01 ]` 序号选框;<br>3. **马达**:发出 300ms 短振提醒成功捕获。 | | **无线对码捕获事件**<br>`RF_PAIR_RECV_EVENT` | **源**LR690L 接收 433MHz 对码载波包。<br>**参数**24-bit 物理地址 + 4-bit 传感器类型数据码。 | **当前状态**`STATE_PAIR_SEARCH` (搜索对码中)。<br>**条件**:捕获到合法 EV1527 帧。 | 1. **状态**:切换至 `STATE_PAIR_CONFIRM` (确认微调)<br>2. **显示**:只读显示自动识别的传感器名称(如 `PORTE`)、大图标,以及超大 `[ 01 ]` 序号选框;<br>3. **马达**:发出 300ms 短振提醒成功捕获。 |
| **传感器入侵警报事件**<br>`RF_ALARM_RECV_EVENT` | **源**LR690L 接收 433MHz 警报载波包。<br>**参数**:传感器地址 + 4-bit 状态码。 | **当前状态**`STATE_CLOCK` (待机)。<br>**条件**1. 地址与 Flash 数据库匹配;<br>2. 该防区属于 ZONE 0 (24h) 或处于已布防状态下的 ZONE 1。 | 1. **状态**:切入 `STATE_ALARMING`<br>2. **显示**LCD 亮起 4px 闪烁红边框与 64x64px 对应传感器报警图标,显示 `PORTE 01 INTRUSION!`<br>3. **灯效**WS2812B 闪烁对应传感器防区色彩500ms闪烁<br>4. **马达**:根据传感器类型,输出对应的间歇振动波形(如门磁短振 1 次)。 | | **传感器入侵警报事件**<br>`RF_ALARM_RECV_EVENT` | **源**LR690L 接收 433MHz 警报载波包。<br>**参数**:传感器地址 + 4-bit 状态码。 | **当前状态**`STATE_CLOCK` (待机)。<br>**条件**1. 地址与 Flash 数据库匹配;<br>2. 该防区属于 ZONE 0 (24h) 或处于已布防状态下的 ZONE 1。 | 1. **状态**:切入 `STATE_ALARMING`<br>2. **显示**LCD 亮起 4px 闪烁红边框与 64x64px 对应传感器报警图标,显示 `PORTE 01 INTRUSION!`<br>3. **灯效**WS2812B 闪烁对应传感器防区色彩500ms闪烁<br>4. **马达**:根据传感器类型,输出对应的间歇振动波形(如门磁短振 1 次)。 |
| **系统自动休眠事件**<br>`AUTO_SLEEP_EVENT` | **源**:软件时钟 `inactivity_timer >= 1000` (10s)。 | **当前状态**`STATE_CLOCK` / `STATE_MENU` / `STATE_SET_TIME` 等非报警状态。 | 1. **状态**:切入 `STATE_SLEEP`<br>2. **硬件**:拉低 `SGM_CTRL = 0` 切断 AMOLED PMIC 供电;<br>3. **电源**:使能 P0 口电平中断及 INT2挂起 CPU 进入 Power-Down 极低功耗模式。 | | **系统自动休眠事件**<br>`AUTO_SLEEP_EVENT` | **源**:软件时钟 `inactivity_timer >= 1000` (10s)。 | **当前状态**`STATE_CLOCK` / `STATE_MENU` / `STATE_SET_TIME` 等非报警状态。 | 1. **状态**:切入 `STATE_SLEEP`<br>2. **硬件**:拉低 `SGM_CTRL = 0` 切断 AMOLED PMIC 供电;<br>3. **电源**:使能 P0 口电平中断及 INT2挂起 CPU 进入 Power-Down 极低功耗模式。 |
| **中断唤醒系统事件**<br>`SYSTEM_WAKEUP_EVENT` | **源**P0口按键沿变化或 INT2 载波接收中断。 | **当前状态**`STATE_SLEEP` (深度休眠中)。 | 1. **状态**:切回 `STATE_CLOCK`<br>2. **电源**:拉高 `SGM_CTRL = 1` 恢复 OLED 供电;<br>3. **延迟**:延时 50ms 避开冲击电流并完成 RM69310 的重初始化;<br>4. **显示**:置 `Redraw = 1` 重绘时钟走时界面。 | | **中断唤醒系统事件**<br>`SYSTEM_WAKEUP_EVENT` | **源**GPIO 端口按键沿变化或 INT2 载波接收中断。 | **当前状态**`STATE_SLEEP` (深度休眠中)。 | 1. **状态**:切回 `STATE_CLOCK`<br>2. **电源**:拉高 `SGM_CTRL = 1` 恢复 OLED 供电;<br>3. **延迟**:延时 50ms 避开冲击电流并完成 RM69310 的重初始化;<br>4. **显示**:置 `Redraw = 1` 重绘时钟走时界面格式。 |
| **IPC 摄像头对码事件**<br>`IPC_BIND_SEND_EVENT` | **源**:在菜单中确认进入 `4. LIAISON`。 | **当前状态**`STATE_IPC_BIND`。 | 1. **无线**:连发 433MHz 手环 Factory ID 及 `0x01` 绑定对码包;<br>2. **显示**:呈现 48x48px 摄像头大图标及 `LIAISON EN COURS`<br>3. **退出**:长按确认键 3 秒或长按 ▼ 键 2 秒,退出并恢复时钟。 | | **IPC 摄像头对码事件**<br>`IPC_BIND_SEND_EVENT` | **源**:在菜单中确认进入 `4. LIAISON`。 | **当前状态**`STATE_IPC_BIND`。 | 1. **无线**:连发 433MHz 手环 Factory ID 及 `0x01` 绑定对码包;<br>2. **显示**:呈现 48x48px 摄像头大图标及 `LIAISON EN COURS`<br>3. **退出**:长按确认键 3 秒或长按 ▼ 键 2 秒,退出并恢复时钟。 |
| **警报解除复位事件**<br>`ALARM_CLEAR_EVENT` | **源**:报警状态下侧边或上部任意按键按下。 | **当前状态**`STATE_ALARMING``STATE_SOS_EMITTED`。 | 1. **状态**:切回 `STATE_CLOCK`<br>2. **灯效**WS2812B 彻底熄灭;<br>3. **马达**:清空马达状态并立即停振;<br>4. **显示**:置 `Redraw = 1`LCD 重绘走时时钟。 | | **警报解除复位事件**<br>`ALARM_CLEAR_EVENT` | **源**:报警状态下侧边或上部任意按键按下。 | **当前状态**`STATE_ALARMING``STATE_SOS_EMITTED`。 | 1. **状态**:切回 `STATE_CLOCK`<br>2. **灯效**WS2812B 彻底熄灭;<br>3. **马达**:清空马达状态并立即停振;<br>4. **显示**:置 `Redraw = 1`LCD 重绘走时时钟。 |

File diff suppressed because it is too large Load Diff