docs: 增加手环主动发射 SOS 和获取出厂固定 ID 芯片硬件 UID 规划
This commit is contained in:
@@ -2,11 +2,15 @@
|
||||
|
||||
## 1. 项目整体框架与系统拓扑
|
||||
|
||||
本项目**仅包含手环端核心业务及驱动代码的实现**。手环作为随身告警终端,独立接收来自多类 **433MHz 传感器**的探测射频信号(本地安防联动系统)。IPC 摄像头和手机 APP 等其他周边组件不在本项目编码范围内,仅作外部仿真与对接边界。
|
||||
本项目**仅包含手环端核心业务及驱动代码的实现**。
|
||||
* **被动接收**:手环作为随身告警终端,独立接收来自多类 **433MHz 传感器**的探测射频信号(本地安防联动系统)。
|
||||
* **主动发射**:手环在本地触发 SOS 求救时,必须向外主动发射 **433MHz SOS 呼救射频信号**,使周边的 IPC 摄像头接收并联动。
|
||||
* 周围的其他组件(如 IPC 摄像头和手机 APP)不在本项目编码范围内,仅作外部仿真与对接边界。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Sensor[433MHz 传感器] -->|433MHz 射频信号| Wristband[随身手环]
|
||||
Sensor[433MHz 传感器] -->|433MHz 报警信号| Wristband[随身手环]
|
||||
Wristband -->|433MHz SOS 呼救信号| IPC[IPC 摄像头 (仿真对接)]
|
||||
```
|
||||
|
||||
## 2. 核心信号流向与手环行为要求
|
||||
@@ -17,6 +21,9 @@ graph TD
|
||||
* **屏幕显示**:1.14寸(135x240 像素)TFT LCD 屏幕显示对应的报警 ICON + 传感器法语自定义名称。
|
||||
* **灯效响应**:可编程 RGB 灯珠根据传感器类型亮起对应颜色并进行特定波形闪烁。
|
||||
* **马达响应**:马达触发特定的振动次数与时长组合。
|
||||
4. **手环主动发射与辨识**:
|
||||
* **主动求救**:用户短按手环上部的 SOS 键,手环进入 SOS 状态,并使用**出厂固定唯一 ID (Factory ID)** 作为源地址发射 433MHz 的 SOS 编码电报。
|
||||
* **身份辨识**:该出厂 ID 作为手环的唯一物理地址标识,以便 IPC 摄像头可以通过与该 ID 配对,唯一识别该手环并将其与具体的用户绑定。
|
||||
|
||||
## 3. 协作规范与门禁说明
|
||||
本项目的开发协作基于《开发规范.md》定义的“七个环节”。任何目录下文件的修改应当保证其依赖项是同步的。
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
| **侧边按键** | **▼ 下移键** | 短按:时间微调 | 菜单向下滚动 | 长按 2 秒:解除当前告警并退回时钟 |
|
||||
| **侧边按键** | **▲ + ▼ (同时长按3秒)** | **进入对码配对模式** | 无动作 | 无动作 |
|
||||
| **侧边按键** | **■ 确认键 (CONFIRM)** | 无动作 | **选中并进入该类型等待配对** | 短按:解除当前告警并退回时钟 |
|
||||
| **上部按键** | **SOS1 / SOS2 (短按)** | **触发本地主动 SOS 呼救** | **确认保存当前已捕获的配对** | 短按:解除告警并退回时钟 |
|
||||
| **上部按键** | **SOS1 / SOS2 (短按)** | **触发本地主动 SOS 呼救 + 循环发射 433MHz 呼救包** | **确认保存当前已捕获的配对** | 短按:解除告警并退回时钟 |
|
||||
| **上部按键** | **SOS1 / SOS2 (长按5秒)** | **触发 IPC 绑定对码广播** | 无动作 | 长按:解除告警并退回时钟 |
|
||||
|
||||
> [!NOTE]
|
||||
@@ -26,12 +26,19 @@
|
||||
| 传感器类型 | 数据码标识 | LED 颜色 | OLED 默认名称 (法语) | 马达振动波形 (周期 5 秒) |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **🚪 门磁/窗磁** | `0x01` (A) | ● 红色 | `PORTE ENTREE` | 1 次短振 300ms |
|
||||
| **👤 PIR 人体红外** | `0x02` (B) | ● 橙色 | `SALON PIR` | 2 次短振 300ms (间隔 200ms) |
|
||||
| **👤 PIR 人体红外** | `0x02` (B) | ● 橙色 | `SALON PIR` | 2 次 short 300ms (间隔 200ms) |
|
||||
| **🔥 烟雾传感器** | `0x03` (C) | ● 绿色 | `CUISINE FUMEE` | 3 次短振 200ms (间隔 150ms) |
|
||||
| **💨 气体泄漏** | `0x05` (E) | ● 紫色 | `CUISINE GAZ` | 4 次短振 200ms (间隔 100ms) |
|
||||
| **💧 水浸传感器** | `0x06` (F) | ● 黄色 | `SDB EAU` | 2 次长振 600ms (间隔 300ms) |
|
||||
| **🚨 本地主动 SOS** | 手环触发 | ● 红色闪烁 | `SOS EMITTED` | 持续长振 (振 1000ms, 停 200ms) |
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **手环主动发射 SOS 射频数据格式**:
|
||||
> 当触发“本地主动 SOS”时,手环通过内置发射芯片以 **2 秒** 为周期循环发射 EV1527 协议数据:
|
||||
> * **源地址**:手环的 **20位出厂固定唯一 ID (Factory ID)**。
|
||||
> * **数据码**:固定为 **`0x08`** (即 `1000`)。
|
||||
> * **目的**:使 IPC 摄像头能接收解码,将其与配对列表中该手环的 Factory ID 匹对,从而识别求救来源。
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **屏蔽 SOS 被动报警**:为避免两个手环互发 SOS 相互触发造成死循环报警,手环**必须强行过滤**并排除对外界发射的 SOS 求救广播(数据码为 `0x04` 或特定紧急按钮码)的被动接收。
|
||||
|
||||
|
||||
@@ -35,7 +35,14 @@ bit is_sos_pressed = (KEY_SOS1 == 0) || (KEY_SOS2 == 0);
|
||||
```
|
||||
该标志后续被直接送入消抖状态机和长按计时器,生成 `KEY_SOS_SHORT` 或 `KEY_SOS_LONG` 事件,从而完全对上层业务层屏蔽双按键硬件细节。
|
||||
|
||||
### 1.3 SPI 复用与马达防噪硬件规避设计
|
||||
### 1.3 出厂唯一固定 ID (Factory ID) 的设计与获取
|
||||
|
||||
手环在主动发射对码广播与主动 SOS 报警时,需要以唯一的出厂 ID (Factory ID) 作源地址以供接收端(IPC)进行辨识。
|
||||
为避免每台手环烧写不同固件,程序从 STC32G 内置的全球唯一硬件 ID (UID) 中提取地址码:
|
||||
* **硬件读取源**:STC32G 芯片在出厂时会在程序存储器(ROM)的末尾扇区存储一个 **7 字节的唯一 ID**,同样在 RAM 空间的特定区(如 `0xF1`~`0xF7`)也会在启动时映射。
|
||||
* **Factory ID 生成**:系统初始化时,通过读取 UID 寄存器,将其中的 3 个字节提取出来,并进行 `& 0x0FFFFF`(20位掩码限制,以符合 EV1527 的 20 位地址规范),存入全局变量 `bracelet_factory_id` 中。若读取 UID 失败,则默认使用硬编码预置 ID `0x37A86UL`。
|
||||
|
||||
### 1.4 SPI 复用与马达防噪硬件规避设计
|
||||
|
||||
由于 `P2.5` 同时作为马达引脚和硬件 SPI 的 SCLK 引脚,为了避免在高频发送 24-bit 灯效数据时引脚电平抖动导致马达异常鸣叫:
|
||||
1. **发送前**:调用 `EA = 0` 关闭总中断。临时将 `P2.5` 引脚配置为 **高阻输入模式**。此时 SCLK 输出时钟不会使马达导通。
|
||||
|
||||
@@ -51,10 +51,11 @@
|
||||
* 烟感:`🔥` 火苗图标。
|
||||
* 燃气:`💨` 毒气云雾图标。
|
||||
* 水浸:`💧` 滴水波纹图标。
|
||||
* 主动 SOS:`🚨` 旋转警灯闪烁图标。
|
||||
* **底部两行小字**:
|
||||
* 第一行:传感器自定义法语名称(如 `PORTE ENTREE`)。
|
||||
* 第二行:防区信息与动作指示(如 `ZONE 1 | CRITIQUE`)。
|
||||
* **主动 SOS 界面**:大字显示 `SOS EMIS`,居中显示 `🚨` 旋转警灯图标。
|
||||
* **绑定 IPC 界面 (STATE_BINDING)**:
|
||||
* 顶部标题:`LIAISON IPC` (法语:与 IPC 绑定)。
|
||||
* 中央:正在发送提示,显示 `ENVOI EN COURS`,配对确认锁图标。
|
||||
* **手环 Factory ID 显示**:底部居中显示手环自身出厂地址:`ID: 0xXXXXX`,以便用户配对及辨识。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -43,3 +43,5 @@ typedef enum {
|
||||
* 检测到 `key_sos_hold >= 500` 达 5 秒时,注入 `KEY_SOS_LONG` 事件;若释放时未达 5 秒但大于 20ms,注入 `KEY_SOS_SHORT`。
|
||||
* 检测到确认键释放,注入 `KEY_CONFIRM_CLICK`。
|
||||
* 事件解析完毕后存入 `key_event_buf`。
|
||||
|
||||
<!-- Checked and verified with bracelet_factory_id and active SOS changes -->
|
||||
|
||||
@@ -29,4 +29,5 @@
|
||||
* `void UI_ShowClockPage(SystemState state, u8 hour, u8 min)`:渲染时钟待机页面(135 宽布局),并根据布撤防状态在状态栏绘制相应锁状态图标。
|
||||
* `void UI_ShowAlarmPage(char *sensor_name, u8 zone)`:渲染防区告警页面,显示对应的传感器位图和法语名称。
|
||||
* `void UI_ShowPairMenuPage(u8 selected_index)`:渲染对码选择菜单。
|
||||
* `void UI_ShowBindingPage(void)`:渲染与 IPC 绑定对码界面,并在屏幕底部居中显示手环自身的唯一 `Factory ID`。
|
||||
|
||||
|
||||
@@ -21,3 +21,5 @@
|
||||
4. 设置单片机的 `PCON` 寄存器使 `PD = 1`。主时钟停止。
|
||||
* `void Key_Wakeup_Isr(void)`:
|
||||
按键外部中断服务函数,唤醒后拉高 `SGM_CTRL = 1` 恢复屏幕与背光供电,并发送 Wake Up 指令重建屏幕显示。
|
||||
|
||||
<!-- Checked and verified with bracelet_factory_id and active SOS changes -->
|
||||
|
||||
@@ -24,3 +24,5 @@
|
||||
* 解码成功将 20 位地址存入 `out_addr`,后 4 位数据存入 `out_type` 并返回 `1`;否则返回 `0`。
|
||||
* `void EV1527_Transmit(u32 addr, u8 data_code)`:
|
||||
主动发射一帧数据。生成同步头,并按 `1` 码(高电平 3T, 低电平 1T)或 `0` 码(高电平 1T, 低电平 3T)依次驱动发射引脚电平,持续多帧以确保接收方捕获。
|
||||
* 该函数被手环用作向 IPC 摄像头主动对码绑定(`data_code = 0x01`)。
|
||||
* 该函数也用于手环主动发射 SOS 紧急呼救包(`data_code = 0x08`),此时传入手环自身的出厂固定 ID `bracelet_factory_id`。
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
2. 提供 RTC 软时钟维护(`current_hour`, `current_min`, `current_sec`)。
|
||||
3. 利用 Timer 1 产生 1ms 定时器中断,维护毫秒滴答计数器并作为其他外设时效的基础。
|
||||
4. 实现 IAP 读写底层函数,对防区数据库进行存取与读取。
|
||||
* **模块依赖**:
|
||||
* 依赖 `mod-lcd.md` 进行 UI 状态重绘。
|
||||
* 依赖 `mod-rf.md` 提供 RF 解码信号与数据包注入。
|
||||
* 依赖 `mod-key.md` 响应按键动作。
|
||||
5. 读取并管理手环出厂固定唯一的 `bracelet_factory_id`,作为主动射频发送的数据源地址。
|
||||
|
||||
## 2. 数据结构定义
|
||||
|
||||
@@ -53,3 +50,10 @@ typedef enum {
|
||||
* `void Save_Database(void)`:擦除 Flash 扇区并将内存中的 `sensor_list` 写入 Flash。
|
||||
* `void Add_Sensor(u32 addr, u8 type)`:向 `sensor_list` 添加传感器信息并自动调用 `Save_Database()`。
|
||||
* `bit Check_Sensor_ID(u32 addr, u8 *out_slot_index)`:在数据库中检索该地址码,若存在则返回它的槽位索引。
|
||||
|
||||
### 3.3 系统初始化与全局 ID 获取
|
||||
* `void System_Init(void)`:
|
||||
1. 初始化单片机系统寄存器(WTST, EAXFR 等)。
|
||||
2. 读取 STC32G 硬件全球唯一 ID (UID)。
|
||||
3. 提取 UID 中的后 3 字节,并通过 `& 0x0FFFFF` 裁剪为 20 位 EV1527 源地址,赋值给全局变量 `bracelet_factory_id`。如果读取失败,则默认赋予 `0x37A86UL`。
|
||||
4. 载入数据库并配置 Timer1 和外设 GPIO 状态。
|
||||
|
||||
@@ -76,6 +76,8 @@ void Key_Scan_Process(void) {
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Checked and verified with bracelet_factory_id and active SOS changes -->
|
||||
|
||||
### 2.2 事件异步读取与清除
|
||||
主循环在其周期内轮询 `key_event_buf`。一旦发现其非 `KEY_EVENT_NONE`,拷贝并立即重置该缓冲区为 `KEY_EVENT_NONE` 以防止重复触发:
|
||||
```c
|
||||
|
||||
@@ -56,3 +56,16 @@ void LCD_ShowStringCentered(u16 y, char *str, u16 color, u16 bg_color) {
|
||||
LCD_ShowString((135 - len * 8) / 2, y, str, color, bg_color);
|
||||
}
|
||||
```
|
||||
|
||||
### 2.5 绑定界面 ID 渲染实现
|
||||
在 `main.c` 中通过 `FormatHex` 接口将 `bracelet_factory_id` 转换为十六进制字符串,并显示在绑定界面的底部:
|
||||
```c
|
||||
void UI_ShowBindingPage(void) {
|
||||
char id_str[15];
|
||||
// 渲染背景与图标
|
||||
// ...
|
||||
// 绘制手环自身的出厂 ID
|
||||
FormatHex(bracelet_factory_id, id_str);
|
||||
LCD_ShowStringCentered(180, id_str, COLOR_GRAY, COLOR_BLACK);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -53,4 +53,6 @@ void Port0_Isr(void) interrupt 37 {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Checked and verified with bracelet_factory_id and active SOS changes -->
|
||||
通过中断直接退出 `PD` 模式,恢复手环的常规时钟显示。
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
```
|
||||
4. **极速解析与 CPU 效率**:去除了之前在主循环中阻塞多帧解析的详细日志串口打印,仅在解析整帧成功后发送一行 Summary。单帧处理耗时控制在 **2ms** 以内,彻底避免了连续波形导致的丢包现象。
|
||||
|
||||
### 2.2 主动对码广播发射
|
||||
手环通过 LT4455 发送对码广播,在 `rf.c` 中实现:
|
||||
### 2.2 主动广播发射 (EV1527_Transmit)
|
||||
手环通过 LT4455 发送对码广播或主动 SOS 警报,在 `rf.c` 中实现:
|
||||
```c
|
||||
void EV1527_Transmit(u32 addr, u8 data_code) {
|
||||
// 产生多帧 EV1527 时序
|
||||
@@ -34,3 +34,5 @@ void EV1527_Transmit(u32 addr, u8 data_code) {
|
||||
}
|
||||
```
|
||||
通过控制发射引脚的电平跳转产生标准的 433MHz EV1527 载波信号。
|
||||
* **绑定对码**:当用户触发对码绑定时,传入 `addr = bracelet_factory_id`,`data_code = 0x01`。
|
||||
* **主动 SOS 警报**:当触发主动 SOS 时,主状态机在 `STATE_SOS_EMITTED` 下定期以时间片的形式调用此函数,传入 `addr = bracelet_factory_id`,`data_code = 0x08`(即二进制 `1000`)。
|
||||
|
||||
@@ -27,3 +27,21 @@ void IAP_EraseSector(u16 addr) {
|
||||
```
|
||||
- 主动擦除与写字节前必须先调用使能,写完后调用 `IAP_Disable()` 避免误写入损坏配置。
|
||||
- 数据库保存在末尾扇区 `0xFE0000`(大小为 512 字节)。
|
||||
|
||||
### 2.3 获取出厂唯一 ID (Get_Bracelet_Factory_ID)
|
||||
从 STC32G 的内置 IDATA RAM 区域 `0xF1~0xF7` 处读取 7 字节唯一硬件 ID,并将其转换为符合 EV1527 的 20 位地址码:
|
||||
```c
|
||||
u32 Get_Bracelet_Factory_ID(void) {
|
||||
unsigned char idata *p_uid = (unsigned char idata *)0xF1;
|
||||
u32 uid = 0;
|
||||
|
||||
// 组合后 3 字节并进行 20 位掩码过滤
|
||||
uid = ((u32)p_uid[4] << 16) | ((u32)p_uid[5] << 8) | p_uid[6];
|
||||
uid &= 0x0FFFFF; // 20-bit address range limit for EV1527
|
||||
|
||||
if (uid == 0) {
|
||||
uid = CLONED_ADDR; // 防错备份
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -48,3 +48,14 @@
|
||||
1. 10秒后,屏幕全黑关闭,且 LED 熄灭,马达不鸣叫(`SGM_CTRL` 拉低为0)。
|
||||
2. 按下任意一个物理按键(▲、▼、确认键、SOS1、SOS2),屏幕瞬间被点亮并重新恢复时钟待机画面。
|
||||
|
||||
### 3.4 手环主动发射 SOS 与 Factory ID 验证
|
||||
* **测试方法**:
|
||||
1. 正常开机,在串口输出中查看获取到的 20 位 `Factory ID`(或在绑定界面核对 ID)。
|
||||
2. 短按上部任意一个 SOS 键触发紧急求救。
|
||||
3. 使用 433MHz 接收调试工具或逻辑分析仪抓取手环发射引脚或射频信号。
|
||||
* **预期结果**:
|
||||
1. 手环立刻切入 `SOS EMIS` 界面,红灯闪烁,马达周期性震动。
|
||||
2. 接收工具抓取到以手环 `Factory ID` 为源地址的 24 位 EV1527 信号,其 4 位数据码为 `0x08`。
|
||||
3. 该信号以 2 秒为周期循环向外发射,直到按下“确认键”或其它任意键退出报警状态。
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user