diff --git a/.xagent/graph.json b/.xagent/graph.json index 64f671a..6abae75 100644 --- a/.xagent/graph.json +++ b/.xagent/graph.json @@ -57,6 +57,20 @@ ], "lock": null }, + "Docs/50_module-breakdown/mod-led.md": { + "depends_on": [ + "Docs/30_architecture/main.md", + "Docs/40_ui-design/main.md" + ], + "lock": null + }, + "Docs/50_module-breakdown/mod-motor.md": { + "depends_on": [ + "Docs/30_architecture/main.md", + "Docs/40_ui-design/main.md" + ], + "lock": null + }, "Docs/60_coding/mod-sys.md": { "depends_on": [ "Docs/50_module-breakdown/mod-sys.md" @@ -87,11 +101,25 @@ ], "lock": null }, + "Docs/60_coding/mod-led.md": { + "depends_on": [ + "Docs/50_module-breakdown/mod-led.md" + ], + "lock": null + }, + "Docs/60_coding/mod-motor.md": { + "depends_on": [ + "Docs/50_module-breakdown/mod-motor.md" + ], + "lock": null + }, "App/main.c": { "depends_on": [ "Docs/60_coding/mod-sys.md", "Docs/60_coding/mod-key.md", - "Docs/60_coding/mod-power.md" + "Docs/60_coding/mod-power.md", + "Docs/60_coding/mod-led.md", + "Docs/60_coding/mod-motor.md" ], "lock": null }, diff --git a/Docs/wristband_ui_gallery.html b/Docs/40_ui-design/wristband_ui_gallery.html similarity index 100% rename from Docs/wristband_ui_gallery.html rename to Docs/40_ui-design/wristband_ui_gallery.html diff --git a/Docs/50_module-breakdown/mod-led.md b/Docs/50_module-breakdown/mod-led.md new file mode 100644 index 0000000..b1c74a7 --- /dev/null +++ b/Docs/50_module-breakdown/mod-led.md @@ -0,0 +1,33 @@ +# 模块拆分 - WS2812B 可编程 RGB 灯效 (Docs/50_module-breakdown/mod-led.md) + +本模块描述可编程幻彩 RGB 灯珠(WS2812B/FCOB-2.7)的单线级联数据流驱动与报警色彩反馈。 + +## 1. 模块职责说明 + +* **职责范围**: + 1. 在系统启动时,配置 WS2812 的物理输出引脚 `P2.3` (MOSI)。 + 2. 提供高速的硬件 SPI 发送驱动,配合 LUT 查表展宽算法,输出满足单线纳秒级精度的 WS2812 时序波形。 + 3. 在硬件 SPI 传输 24位灯效数据时,采取临时关闭中断并把复用的 `P2.5` 配置为高阻输入的隔离防噪处理。 + 4. 维护软件定时闪烁状态机,提供报警状态下的指示灯颜色与特定频率闪烁效果。 + +## 2. LED 报警色彩矩阵 + +根据 7 种不同的外部传感器类型及本地主动求救,亮起对应的 LED 灯: +* **门磁/窗磁 (PORTE)**:红色闪烁。 +* **PIR 人体红外 (PIR)**:橙色闪烁。 +* **烟雾传感器 (FUMEE)**:绿色闪烁。 +* **紧急按钮 (URGENCE)**:蓝色闪烁。 +* **气体泄漏 (GAZ)**:紫色闪烁。 +* **水浸传感器 (INOND.)**:黄色闪烁。 +* **振动传感器 (VIBRA.)**:青色闪烁。 +* **本地主动 SOS**:红色快速交替闪烁。 + +## 3. 接口与函数说明 + +* `void WS2812_Init(void)`:配置 `P2.3` 引脚为推挽输出模式。 +* `void WS2812_Write24Bit(u8 g, u8 r, u8 b)`:使用硬件 SPI 方式串行发送 24-bit 颜色数据给级联灯珠。发送前后进行 `P2.5` 引脚高阻/推挽切换屏蔽马达时钟抖动。 +* `void WS2812_Reset(void)`:发送大于 80us 的低电平复位脉冲使颜色锁存生效。 +* `void LED_Set_Color(u8 g, u8 r, u8 b)`:立即设置 RGB 灯亮起特定颜色。 +* `void LED_Flash_Process(void)`:在 1ms 定时器中断中累加,控制报警状态下指示灯的交替闪烁(如 500ms 亮、500ms 灭)。 + + diff --git a/Docs/50_module-breakdown/mod-motor.md b/Docs/50_module-breakdown/mod-motor.md new file mode 100644 index 0000000..c43f681 --- /dev/null +++ b/Docs/50_module-breakdown/mod-motor.md @@ -0,0 +1,32 @@ +# 模块拆分 - 振动马达驱动与反馈 (Docs/50_module-breakdown/mod-motor.md) + +本模块描述手环告警与按键反馈的振动马达驱动逻辑。手环通过控制特定的振动时长与周期,向用户提供直观的物理触觉告警反馈。 + +## 1. 模块职责说明 + +* **职责范围**: + 1. 系统初始化时,将马达控制管脚 `P2.5` 配置为推挽输出模式。 + 2. 提供底层的开关控制,使能或禁止马达供电(高电平振动,低电平静止)。 + 3. 在 1ms 中断(Timer 1)中执行异步振动控制时序(Pulse Process),实现不阻塞 CPU 的各种复杂振动波形(如短振、长振、连续多次振动)。 + 4. 根据接收到的 7 类传感器报警类型或本地主动 SOS 呼救状态,自动触发对应的振动模式。 + +## 2. 振动模式设计 (周期 5 秒) + +* **门磁/窗磁 (PORTE)**:1 次短振 300ms。 +* **PIR 红外 (PIR)**:2 次短振 300ms (间隔 200ms)。 +* **烟雾传感器 (FUMEE)**:3 次短振 200ms (间隔 150ms)。 +* **紧急按钮 (URGENCE)**:1 次长振 800ms。 +* **气体泄漏 (GAZ)**:4 次短振 200ms (间隔 100ms)。 +* **水浸传感器 (INOND.)**:2 次长振 600ms (间隔 300ms)。 +* **振动传感器 (VIBRA.)**:连续 3 次短振 150ms (间隔 100ms)。 +* **本地主动 SOS**:持续性间歇长振(振 1000ms,停 200ms 循环)。 + +## 3. 接口与函数说明 + +* `void Motor_Init(void)`:初始化配置引脚 `P2.5` 为推挽输出,默认输出低电平(马达静止)。 +* `void Motor_Set_State(bit state)`:立即开关马达(直接写入 `P2.5` 引脚)。 +* `void Motor_Start_Alarm_Pattern(u8 pattern_type)`:传入传感器类型,装载对应的振动计数器和阶段标志,启动异步振动模式。 +* `void Motor_Pulse_Process(void)`:在 1ms 中断中调用(通常每 10ms 调度一次),更新振动时间计数器,切换各阶段电平以输出指定波形。 +* `void Motor_Stop(void)`:清空所有计数器并立即关闭马达,用以清除告警。 + + diff --git a/Docs/60_coding/mod-led.md b/Docs/60_coding/mod-led.md new file mode 100644 index 0000000..8713f74 --- /dev/null +++ b/Docs/60_coding/mod-led.md @@ -0,0 +1,123 @@ +# 编码实现 - WS2812B 可编程 RGB 灯效 (Docs/60_coding/mod-led.md) + +本文件对应可编程幻彩 RGB 灯珠硬件 SPI 驱动与报警指示灯控的编码实现细节。 + +## 1. 对应代码源文件 + +* [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (定义 SPI 配置、展宽查表及 1ms 定时中断中的闪烁控制) + +## 2. 关键代码片段与逻辑实现 + +### 2.1 驱动初始化与管脚分配 +WS2812B 输入脚接在单片机硬件 SPI 组管脚中的 MOSI (`P2.3`): +```c +sbit WS2812_DI = P2^3; + +void WS2812_Init(void) { + // P2.3 (MOSI) 配置为推挽输出,默认输出低电平 0 + P2M1 &= ~(1 << 3); + P2M0 |= (1 << 3); + WS2812_DI = 0; +} +``` + +### 2.2 硬件 SPI 防噪声极速发送 (WS2812_Write24Bit) +由于 SPI 时钟 SCLK 与马达引脚复用 `P2.5`,发送期间关闭总中断并将 `P2.5` 设为高阻输入以规避马达杂音,通过 SPDAT 展开 24bit 数据串行输出。 +展宽 LUT 定义: +```c +const u16 code SPI_LUT[16] = { + 0x924, 0x926, 0x934, 0x936, 0x9A4, 0x9A6, 0x9B4, 0x9B6, + 0xD24, 0xD26, 0xD34, 0xD36, 0xDA4, 0xDA6, 0xDB4, 0xDB6 +}; +``` +发送函数实现: +```c +void WS2812_Write24Bit(u8 g, u8 r, u8 b) { + u8 data buf[10]; + u8 b0, b1, b2, b3, b4, b5, b6, b7, b8, b9; + + buf[0] = 0x00; // 虚拟前导字节,吸收硬件启动瞬态抖动 + WS2812_EncodeByte(g, &buf[1]); + WS2812_EncodeByte(r, &buf[4]); + WS2812_EncodeByte(b, &buf[7]); + + b0 = buf[0]; b1 = buf[1]; b2 = buf[2]; b3 = buf[3]; + b4 = buf[4]; b5 = buf[5]; b6 = buf[6]; b7 = buf[7]; + b8 = buf[8]; b9 = buf[9]; + + EA = 0; // 关中断保证 SPI 传输的连续性 + + // 配置 P2.5 为高阻输入模式,屏蔽马达噪声 + P2M1 |= (1 << 5); + P2M0 &= ~(1 << 5); + + SPSTAT = 0xC0; // 清除 SPI 状态寄存器 + SPDAT = b0; // 发送数据 + SPCTL = 0xD0; // 开启 SPI 硬件传输 + + // 展开的非阻塞高速发送时序 (300ns 传输间隔) + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b1; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b2; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b3; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b4; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b5; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b6; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b7; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b8; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b9; + while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; + + SPCTL = 0x90; // 关闭 SPI 硬件使能 + WS2812_DI = 0; + + // 恢复 P2.5 为推挽输出,控制马达常规功能 + P2M1 &= ~(1 << 5); + P2M0 |= (1 << 5); + MOTOR = 0; // 确保马达断开 + + EA = 1; // 恢复中断 +} + +void WS2812_Reset(void) { + WS2812_DI = 0; + // 延时 > 80us 触发重置 + { + u8 i; + for (i = 0; i < 100; i++) { + _nop_(); + } + } +} +``` + +### 2.3 报警状态交替闪烁逻辑 (LED_Flash_Process) +在 `Timer1_Isr` (每 10ms 调用一次) 中,管理指示灯闪烁状态: +```c +u16 led_flash_time = 0; +bit led_flash_state = 0; +bit led_running_flag = 0; +u8 led_color_r = 0, led_color_g = 0, led_color_b = 0; + +void LED_Flash_Process(void) { + if (!led_running_flag) { + WS2812_Write24Bit(0, 0, 0); // 关闭 LED + WS2812_Reset(); + return; + } + + led_flash_time += 10; + if (led_flash_time >= 500) { // 500ms 交替周期 + led_flash_time = 0; + led_flash_state = ~led_flash_state; + + if (led_flash_state) { + WS2812_Write24Bit(led_color_g, led_color_r, led_color_b); + } else { + WS2812_Write24Bit(0, 0, 0); + } + WS2812_Reset(); + } +} +``` + + diff --git a/Docs/60_coding/mod-motor.md b/Docs/60_coding/mod-motor.md new file mode 100644 index 0000000..27172c5 --- /dev/null +++ b/Docs/60_coding/mod-motor.md @@ -0,0 +1,119 @@ +# 编码实现 - 振动马达驱动与反馈 (Docs/60_coding/mod-motor.md) + +本文件对应振动马达异步时序控制的编码实现细节。 + +## 1. 对应代码源文件 + +* [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (定义马达引脚控制及 1ms 中断中的异步脉冲状态机处理) + +## 2. 关键代码片段与逻辑实现 + +### 2.1 引脚控制宏与初始化 +马达由引脚 `P2.5` 控制。配置模式为推挽输出: +```c +sbit MOTOR = P2^5; + +void Motor_Init(void) { + // 将 P2.5 配置为推挽输出模式,默认输出低电平 0 + P2M1 &= ~(1 << 5); + P2M0 |= (1 << 5); + MOTOR = 0; +} +``` + +### 2.2 异步定时脉冲时序控制 (Motor_Pulse_Process) +为了避免采用阻塞式的 `Delay` 函数占用 CPU,我们在 1ms 定时中断中实现非阻塞状态机。 +定义全局控制变量: +```c +u16 motor_pattern_time = 0; // 阶段累计计数器 +u8 motor_phase = 0; // 振动阶段指示器 +u8 motor_total_pulses = 0; // 当前告警所需触发的总脉冲数 +u8 motor_pulse_count = 0; // 已振动次数 +u16 motor_on_ms = 0; // 单次振动持续时间 +u16 motor_off_ms = 0; // 振动间隔休眠时间 +bit motor_running_flag = 0; // 正在振动告警指示标志 +``` + +在 `Timer1_Isr` (每 10ms 调用一次) 中驱动该状态机: +```c +void Motor_Pulse_Process(void) { + if (!motor_running_flag) { + MOTOR = 0; + return; + } + + motor_pattern_time += 10; + + if (motor_phase == 0) { + // 振动阶段 + MOTOR = 1; + if (motor_pattern_time >= motor_on_ms) { + MOTOR = 0; + motor_pattern_time = 0; + motor_phase = 1; // 切换到休眠阶段 + } + } + else if (motor_phase == 1) { + // 休眠间隔阶段 + MOTOR = 0; + if (motor_pattern_time >= motor_off_ms) { + motor_pattern_time = 0; + motor_pulse_count++; + + if (motor_pulse_count >= motor_total_pulses) { + // 已达到指定次数,停止当前周期振动 + MOTOR = 0; + motor_running_flag = 0; + } else { + motor_phase = 0; // 继续下一次振动 + } + } + } +} +``` + +### 2.3 启动与重置接口 +```c +void Motor_Start_Alarm_Pattern(u8 type) { + motor_pattern_time = 0; + motor_phase = 0; + motor_pulse_count = 0; + + switch (type) { + case 0: // 🚪 门磁: 1 次短振 300ms + motor_on_ms = 300; motor_off_ms = 5000; motor_total_pulses = 1; + break; + case 1: // 👤 PIR: 2 次短振 300ms + motor_on_ms = 300; motor_off_ms = 200; motor_total_pulses = 2; + break; + case 2: // 🔥 烟感: 3 次短振 200ms + motor_on_ms = 200; motor_off_ms = 150; motor_total_pulses = 3; + break; + case 3: // 🆘 紧急按钮: 1 次长振 800ms + motor_on_ms = 800; motor_off_ms = 5000; motor_total_pulses = 1; + break; + case 4: // 💨 气体: 4 次短振 200ms + motor_on_ms = 200; motor_off_ms = 100; motor_total_pulses = 4; + break; + case 5: // 💧 水浸: 2 次长振 600ms + motor_on_ms = 600; motor_off_ms = 300; motor_total_pulses = 2; + break; + case 6: // 📳 振动: 3 次短振 150ms + motor_on_ms = 150; motor_off_ms = 100; motor_total_pulses = 3; + break; + case 7: // 🚨 本地主动 SOS: 循环长振 + motor_on_ms = 1000; motor_off_ms = 200; motor_total_pulses = 0xFF; // 近似无限循环 + break; + default: + return; + } + motor_running_flag = 1; +} + +void Motor_Stop(void) { + motor_running_flag = 0; + MOTOR = 0; +} +``` + +