Files
stc32g128k/Docs/30_architecture/main.md

285 lines
17 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.

# 架构设计说明书 (Docs/30_architecture/main.md)
本章节定义手环的系统软硬件架构设计,包括引脚分配、核心状态机迁移关系、持久化数据存储结构以及软件分层框架与主循环调度流程。
---
## 1. 硬件原理图与引脚分配架构
手环的完整电路连接设计参见以下 KiCad 硬件工程文件:
* **硬件原理图**[text.kicad_sch](file:///c:/workfile/105/stc32g12k128/Hardware/text.kicad_sch)
* **PCB 布局图**[text.kicad_pcb](file:///c:/workfile/105/stc32g12k128/Hardware/text.kicad_pcb)
主控芯片采用 **STC32G12K128**(工作频率 24.0 MHz单周期 8051 内核32位乘除法器
显示端采用 **Truly 0.95寸 AMOLED 屏幕**,物理分辨率为 **120x240 像素**,控制芯片为 **RM69310**
### 1.1 GPIO 物理映射表
| 引脚号 | 引脚名称 | IO 模式 | 连接外设与功能描述 |
| :--- | :--- | :--- | :--- |
| **P0.0** | `BAT_ADC` | 模拟输入 | 电池电压采样输入端口,对应硬件 ADC 通道 8 (A8) |
| **P0.1** | `KEY_UP` | 高阻输入+上拉 | 侧边按键 ▲ (上移),按下为低电平 |
| **P0.2** | `KEY_SOS1` | 高阻输入+上拉 | 上部按键 SOS 1按下为低电平 |
| **P0.3** | `KEY_DOWN` | 高阻输入+上拉 | 侧边按键 ▼ (下移),按下为低电平 |
| **P0.4** | `KEY_CONFIRM`| 高阻输入+上拉 | 侧边按键 ■ (确认),按下为低电平 |
| **P0.5** | `KEY_SOS2` | 高阻输入+上拉 | 上部按键 SOS 2按下为低电平 |
| **P1.1** | `LCD_RST` | 推挽输出 | LCD 屏幕复位引脚 |
| **P1.3** | `LCD_RS` | 推挽输出 | LCD 屏幕 SPI 数据/命令寄存器选择 (D/C) |
| **P1.4** | `LCD_CS` | 推挽输出 | LCD 屏幕 SPI 片选信号 |
| **P1.5** | `LCD_SCL` | 推挽输出 | LCD 屏幕 SPI 时钟信号 |
| **P1.6** | `LCD_SDA` | 推挽输出 | LCD 屏幕 SPI 数据信号 |
| **P2.3** | `WS2812_DI` | SPI MOSI | 连接可编程双级联 RGB 灯珠的 DIN 信号输入 |
| **P2.5** | `MOTOR` | 推挽输出 | 连接振动马达驱动电路。高电平震动,低电平静止 |
| **P2.7** | `USB_DET` | 高阻输入 | USB 插入充电检测引脚,高电平代表正在充电 |
| **P3.4** | `SGM_CTRL` | 推挽输出 | OLED 供电芯片 SGM3833 控制引脚。高电平使能,低电平关闭 |
---
## 2. 软件核心业务状态机
系统包含 10 个业务状态,其状态迁移关系如下图所示:
```mermaid
stateDiagram-v2
[*] --> STATE_CLOCK
%% 休眠与唤醒
STATE_CLOCK --> STATE_SLEEP : 10秒无操作超时
STATE_SLEEP --> STATE_CLOCK : 中断唤醒 (按键/无线信号)
%% 主选择菜单迁移
STATE_CLOCK --> STATE_MENU : CONFIRM 长按 3 秒
STATE_MENU --> STATE_CLOCK : CONFIRM 长按 3 秒 / 10秒无操作超时
STATE_MENU --> STATE_SLEEP : 10秒无操作超时
%% 子设置页面迁移
STATE_MENU --> STATE_SET_TIME : 选中 "1. DATE/HEURE" + 确认键单击
STATE_SET_TIME --> STATE_CLOCK : 保存退出 / 10秒无操作超时
STATE_MENU --> STATE_PAIR_SEARCH : 选中 "2. APPAIRAGE" + 确认键单击
STATE_PAIR_SEARCH --> STATE_PAIR_CONFIRM : 捕获 433MHz 传感器数据 (自动识别传感器类型)
STATE_PAIR_CONFIRM --> STATE_CLOCK : 序号微调后 CONFIRM 确认保存
STATE_PAIR_SEARCH --> STATE_MENU : 长按 ▼ 键退出
STATE_MENU --> STATE_ARM_DISARM_SELECT : 选中 "3. ARM/DISARM" + 确认键单击
STATE_ARM_DISARM_SELECT --> STATE_CLOCK : 选择完成并返回
STATE_MENU --> STATE_IPC_BIND : 选中 "4. LIAISON IPC" + 确认键单击
STATE_IPC_BIND --> STATE_CLOCK : 发射结束 / 确认键长按 3s 退出 / ▼键长按 2s 退出
%% 报警迁移
STATE_CLOCK --> STATE_SOS_EMITTED : 按下上部任意 SOS 键 (点击/长按)
STATE_SLEEP --> STATE_SOS_EMITTED : 中断唤醒直接报警
STATE_SOS_EMITTED --> STATE_CLOCK : 按任意键/超时退出
STATE_CLOCK --> STATE_ALARMING : 捕获已配对传感器报警 (ZONE 0 或布防下的 ZONE 1)
STATE_ALARMING --> STATE_CLOCK : 按任意键/超时退出
```
### 2.1 低功耗设计与唤醒架构
为实现超低功耗,系统在 `STATE_SLEEP` 状态下使用以下硬件与软件协同设计:
1. **彻底切断 PMIC**:拉低 `SGM_CTRL = 0`,使 SGM3833 停止工作,彻底消除 Truly AMOLED 屏的负压静态功耗。
2. **休眠配置**:允许 P0 口电平变化中断与射频接收引脚的中断使能。
3. **进入停机**:将单片机挂起写入 `PCON |= 0x02` 进入停机模式,关闭主时钟。
4. **中断唤醒**:按键按下或 LR690L 接收到载波变化时,触发中断唤醒 MCUISR 立即拉高 `SGM_CTRL = 1` 并延时约 50ms 重新初始化 RM69310 屏幕控制器以恢复显示。
---
## 3. 持久化配置数据库架构
为了确保配对数据掉电不丢失,手环使用内置 IAP 读写 Flash 扇区:
* **物理存储扇区**`0xFE0000` (末尾扇区,大小为 512 字节)。
* **数据库容量**:共 16 组传感器配置槽位。
* **存储结构定义**
```c
typedef struct {
u8 is_used; // 有效标志 (0x01: 有效, 其它: 空闲)
u8 addr[3]; // 24位射频物理地址 (EV1527)
u8 type; // 传感器类型 (0: 门磁, 1: 红外, 2: 烟感, 3: 紧急, 4: 气体, 5: 水浸, 6: 振动)
u8 zone; // 防区类别 (0: 永久防区, 1: 普通可撤布防区)
char name_gbk[16]; // 法语自定义防区名称 (格式化为: [名前缀] [两位序号])
} Sensor_Slot;
```
---
## 4. 软件层级架构与核心代码框架
软件系统采用 **非阻塞** 的三层级模块化架构设计:
```mermaid
graph TD
subgraph Layer3 [应用层 (APP)]
MainScheduler[主循环轮询 & 喂狗]
SysStateMachine[SystemState 业务状态机]
SoftRTC[软件 RTC 计时器]
end
subgraph Layer2 [外设驱动层 (DRV)]
AMOLED[RM69310 AMOLED 屏幕绘制]
RF[LR690L 编解码 & 过滤 0x08 SOS 信号]
KEY[按键消抖 & 长按长计时]
PM[低功耗休眠与唤醒]
LED[WS2812B 级联双彩灯时序]
MOTOR[振动马达脉冲时序]
end
subgraph Layer1 [硬件抽象与时基层 (HW)]
Timer1[Timer 1 中断 (1ms 滴答)]
ADC[12位电压采集]
Flash[IAP 读写]
GPIO[数字 I/O 与电平中断]
end
Layer1 --> Layer2
Layer2 --> Layer3
```
### 4.1 核心主程序调度框架 (main.c)
主程序采用完全解耦的时间片轮询加事件触发的非阻塞循环结构:
```c
#include "config.h"
// 全局状态变量
SystemState current_state;
u16 inactivity_timer;
u32 rx_addr;
u8 rx_type;
void main(void) {
// 1. 初始化底层硬件与外设驱动
System_Init();
Power_Init(); // SGM_CTRL 默认拉高工作
LCD_Init(); // Truly AMOLED 初始化
RF_Init(); // LR690L 接收中断与发射初始化
WS2812_Init(); // 双级联彩灯初始化
Motor_Init(); // 马达脉冲时序初始化
ADC_Init(); // 电池采样初始化
// 2. 载入持久化数据配置
Load_Database();
// 3. 初始化软件状态与计时器
current_state = STATE_CLOCK;
inactivity_timer = 0;
Redraw = 1;
// 开启全局中断
EA = 1;
// 4. 核心主循环轮询调度
while (1) {
// A. 轮询射频接收
if (EV1527_Decode(&rx_addr, &rx_type)) {
inactivity_timer = 0; // 重置休眠计数
Process_RF_Event(rx_addr, rx_type);
}
// B. 轮询并消耗按键事件
if (key_event_buf != KEY_EVENT_NONE) {
KeyEvent evt = key_event_buf;
key_event_buf = KEY_EVENT_NONE; // 清空事件
inactivity_timer = 0; // 重置休眠计数
Process_System_Event(evt);
}
// C. 超时低功耗检测判定
if (inactivity_timer >= 1000) { // 10秒无操作
inactivity_timer = 0;
current_state = STATE_SLEEP;
// 执行硬件关屏断电并让单片机进入深度休眠
Enter_Low_Power_Sleep();
// 被外部中断唤醒后从此处开始继续向下运行,执行电源与显示恢复
Wakeup_Restore();
current_state = STATE_CLOCK;
Redraw = 1;
}
// D. 屏幕刷新渲染调度
if (Redraw) {
Redraw = 0; // 清除标志
Render_UI_Screen(current_state);
}
// E. 喂狗操作
WDT_CONTR = 0x17;
}
}
```
---
## 5. 模块间输入/输出事件与流转处理消耗图
为了使各功能模块Drivers & App交互逻辑清晰可见下表整理了各模块产生的事件源输入及其被消费输出的处理链路
### 5.1 模块输入/输出事件矩阵
| 模块名称 | 输入源 (触发源) | 产生/发出事件 | 输出消费对象 (消费处理) |
| :--- | :--- | :--- | :--- |
| **按键模块 (KEY)** | 物理引脚P0.1~P0.5)电平状态改变 | `KeyEvent`<br>- `KEY_UP_SHORT` / `KEY_DOWN_SHORT`<br>- `KEY_DOWN_LONG` (长按▼ 2秒)<br>- `KEY_CONFIRM_CLICK`<br>- `KEY_CONFIRM_LONG` (长按■ 3秒)<br>- `KEY_SOS_SHORT` / `KEY_SOS_LONG` (SOS键短按或长按) | 写入全局事件缓冲队列 `key_event_buf`。由 **APP 应用状态机** 读出后用于控制页面导航、退出告警或启动对码。 |
| **无线射频 (RF)** | LR690L 433MHz 载波信号接收(输入电平变化) | `RFEvent` (包含 `rx_addr``rx_type`) | 传递至 **APP 状态机**`Process_RF_Event` 进行报警分发。 |
| **状态机 (APP)** | 消耗 `key_event_buf``RFEvent` | `SysState` 业务状态跳转及动作指令 | 1. 改变 `current_state` 并设置 `Redraw = 1`<br>2. 调度 **LED****MOTOR** 开启报警灯效/马达振动;<br>3. 写入 **IAP Flash 数据库** 配对记录;<br>4. 调用 **RF** 发送 `0x01` (IPC对码) 或 `0x08` (主动SOS)。 |
| **显示模块 (LCD)** | 状态机重绘请求 `Redraw == 1` | SPI 串行像素显示数据流 | 驱动 **Truly AMOLED** 渲染当前状态所对应的时钟、主菜单、对码、时间设定或报警画面。 |
| **供电管理 (POWER)**| 1. `inactivity_timer >= 1000` (10秒超时)<br>2. 中断唤醒信号 (GPIO/INT2) | 电源电平控制及停机状态 | 1. **进入休眠**:发出关屏指令 $
ightarrow$ 拉低 `SGM_CTRL = 0` $
ightarrow$ 执行停机挂起(主循环暂停在 `Enter_Low_Power_Sleep` 内);<br>2. **唤醒恢复**:拉高 `SGM_CTRL = 1` $
ightarrow$ 延时 50ms $
ightarrow$ 重新初始化 RM69310 屏幕控制器(主循环恢复运行并在待机页重新走时)。 |
| **彩灯模块 (LED)** | 状态机调用报警指示请求 | SPI 48-bit 灯珠级联控制字 | 向两颗级联的 WS2812B 发送颜色数据(报警时交替闪烁,配对时常亮)。 |
| **马达模块 (MOTOR)**| 状态机请求按键反馈/告警振动 | IO 电平状态控制字 (P2.5) | 定时驱动 `P2.5` 引脚电平产生不同振动波形(如短振、长振、间歇循环振动)。 |
### 5.2 事件流转与消费链路拓扑
手环系统的输入事件(按键中断与无线载波中断)在主循环中的处理与消耗流转关系如下:
```mermaid
flowchart TD
%% 硬件输入事件
PinKey[物理按键按下 / 下降沿] -->|P0.1-P0.5 端口中断| ISR_Port0[Port0 中断 ISR]
Carrier[433MHz 射频载波信号] -->|INT2 中断| ISR_INT2[INT2 唤醒中断 ISR]
%% 中断服务层 (ISR)
ISR_Port0 -->|唤醒系统并每10ms扫描| KeyScan[消抖与长短按判定]
ISR_INT2 -->|唤醒系统并使能软解码| RFDecode[EV1527 自适应比值解码]
%% 事件过滤与缓冲层
KeyScan -->|判定有效按键事件| BufKey[写入 key_event_buf 缓冲区]
RFDecode --> ProcessRF[生成合法传感器 RFEvent]
%% APP 状态机消费处理
BufKey -->|主循环读取并重置| SM_Key[消费按键事件]
ProcessRF -->|主循环调用并比对配置| SM_RF[消费已配对防区报警]
SM_Key -->|CONFIRM 长按 3s| StateMenu[切入 STATE_MENU 并 Redraw=1]
SM_Key -->|子页面确认操作| StateSub[执行配对/布防/时间设定并 IAP 写入]
SM_Key -->|点击/长按 SOS 键| EmitSOS[调用 RF 主动发射 0x08 SOS 信号]
SM_Key -->|告警状态任意键| ClearAlarm[清除本地报警状态并退回时钟]
SM_RF -->|匹配成功且处于布防| LocalAlarm[触发 LED 交替闪烁 & 马达间歇振动]
%% 显示与控制响应
StateMenu -->|Redraw == 1| LcdPaint[Truly AMOLED 屏幕局部像素重绘]
StateSub -->|Redraw == 1| LcdPaint
LocalAlarm -->|Redraw == 1| LcdPaint
EmitSOS -->|Redraw == 1| LcdPaint
```
---
## 6. 核心业务事件输入输出 (I/O) 架构明细表
为实现绝对清晰的软硬件交互链路,以下为手环核心业务事件的端到端输入、输出及流转逻辑汇总:
### 6.1 核心事件 I/O 矩阵
| 事件名称 | 输入源 (触发条件与参数) | 状态机判定逻辑 (当前状态与条件) | 输出结果 & 动作执行 (显示、灯效、马达与无线) |
| :--- | :--- | :--- | :--- |
| **按键操作事件**<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>`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_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>`SYSTEM_WAKEUP_EVENT` | **源**P0口按键沿变化或 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 秒,退出并恢复时钟。 |
| **警报解除复位事件**<br>`ALARM_CLEAR_EVENT` | **源**:报警状态下侧边或上部任意按键按下。 | **当前状态**`STATE_ALARMING``STATE_SOS_EMITTED`。 | 1. **状态**:切回 `STATE_CLOCK`<br>2. **灯效**WS2812B 彻底熄灭;<br>3. **马达**:清空马达状态并立即停振;<br>4. **显示**:置 `Redraw = 1`LCD 重绘走时时钟。 |