#include "stc32g.h" #include "intrins.h" #include "config.h" #include "../Drivers/lcd.h" #include "../Drivers/rf.h" /* ========================================================================= * 硬件引脚与全局变量定义 * ========================================================================= */ // 软件虚拟 LED 状态变量(0表示亮,1表示灭,兼容原有代码逻辑) bit LED_R = 1; bit LED_G = 1; bit LED_B = 1; bit last_hw_r = 1; bit last_hw_g = 1; bit last_hw_b = 1; bit rgb_test_mode = 0; // 实际 WS2812 物理控制引脚(接 P0.0) sbit WS2812_DI = P2^3; // 振动马达控制引脚(输出1开启振动,输出0停止) sbit MOTOR = P2^5; // 板载独立按键(按下时为低电平,利用内部上拉电阻) sbit KEY_UP = P0^1; // SW1 按键 sbit KEY_SOS = P0^2; // SW3 按键 sbit KEY_DOWN = P0^3; // SW2 按键 // 系统运行状态变量与时钟 SystemState current_state = STATE_NORMAL; // 当前系统状态,默认是时钟待机 u8 current_hour = 10; // 系统小时时钟 u8 current_min = 35; // 系统分钟时钟 u8 current_sec = 0; // 系统秒时钟 volatile u8 clock_updated = 0; // 分钟变化刷新标志 u8 menu_select = 0; // 对码菜单选中的传感器类型索引 (0~4) u32 captured_addr = 0; // 射频接收捕获到的临时24位地址码 u8 captured_type = 0; // 射频接收捕获到的临时传感器类型 u8 alarm_sensor_slot = 0; // 正在报警的传感器槽位索引 // 传感器配对记录表 (16组槽位,保存在 xdata 中,防内存溢出) Sensor_Slot xdata sensor_list[16]; // 系统软件计数滴答(由定时器1 ms中断累加维护) volatile u16 ms_tick = 0; // 毫秒计数器 (0~999) volatile u32 pair_timeout_ms = 0; // 对码等待超时计数器 (最大 30000ms) volatile u16 alarm_timer_ms = 0; // 警报声光闪烁定时器 volatile u16 motor_timer_ms = 0; // 马达振动波形定时器 volatile bit alarm_flash_flag = 0; // 闪烁标志状态位 // 独立按键消抖、长按与组合判定的软件计数器 volatile u16 key_scan_timer = 0; // 10ms按键扫描定时计数器 volatile u16 key_up_hold = 0; // SW1按键按下维持时间 (单位: 10ms) volatile u16 key_down_hold = 0; // SW2按键按下维持时间 (单位: 10ms) volatile u16 key_sos_hold = 0; // SW3按键按下维持时间 (单位: 10ms) volatile u16 comb_hold = 0; // SW1+SW2组合键按下维持时间 (单位: 10ms) volatile KeyEvent key_event_buf = KEY_EVENT_NONE; // 按键事件缓冲区 /* ========================================================================= * 辅助映射表及前置声明 * ========================================================================= */ // 各防区类型的默认法语防区名称 (供报警显示使用,最大15字符) char *code default_names[5] = { "PORTE ENTREE", // 0: 门磁 "SALON PIR", // 1: 红外 "CUISINE FUMEE", // 2: 烟感 "CUISINE GAZ", // 3: 燃气 "SDB EAU" // 4: 水浸 }; // 各防区类型的默认防区类别 (0: 24小时防区-撤防亦报警, 1: 普通防区-仅布防下报警) u8 code default_zones[5] = {1, 1, 0, 0, 0}; // 对码选择菜单显示的各条目字符串 (法语,最大15字符) char *code menu_items[5] = { "DETEC. PORTE", // 0 "DETEC. PIR", // 1 "DETEC. FUMEE", // 2 "DETEC. GAZ", // 3 "DETEC. EAU" // 4 }; // 本地函数前置声明 void Delay10us(void); void GPIO_Init(void); void Timer1_Init(void); u16 GetTimer0_Safe(void); void Delay_us(u16 us); void Delay_ms(u16 ms); void Uart1_Init(void); void Uart_SendByte(u8 dat); void Uart_SendString(char *s); char Uart_RxChar(void); void Uart_SendHex4(u8 val); void Uart_SendHex8(u8 val); void Uart_SendHex20(u32 val); void Uart_SendHex32(u32 val); void Uart_SendHex16(u16 val); void FormatHex(u32 val, char *buf); // IAP 闪存读写底层声明 void IAP_Disable(void); u8 IAP_ReadByte(u16 addr); void IAP_WriteByte(u16 addr, u8 dat); void IAP_EraseSector(u16 addr); void Load_Database(void); void Save_Database(void); void Add_Sensor(u32 addr, u8 type); bit Check_Sensor_ID(u32 addr, u8 *out_slot_index); // UI 绘制层接口声明 void UI_ShowClockPage(SystemState state, u8 hour, u8 min); void UI_ShowPairMenuPage(u8 selected_index); void UI_ShowPairWaitPage(u8 frame_index); void UI_ShowPairConfirmPage(u32 addr); void UI_ShowPairSuccessPage(u32 addr); void UI_ShowPairFailPage(u8 is_timeout); void UI_ShowAlarmPage(char *sensor_name, u8 zone); void UI_ShowSosPage(void); /* ========================================================================= * WS2812B 幻彩 LED 单线驱动函数 (24MHz 1T 模式下精准时序控制) * ========================================================================= */ const u16 code SPI_LUT[16] = { 0x924, 0x926, 0x934, 0x936, 0x9A4, 0x9A6, 0x9B4, 0x9B6, 0xD24, 0xD26, 0xD34, 0xD36, 0xDA4, 0xDA6, 0xDB4, 0xDB6 }; void WS2812_EncodeByte(u8 v, u8 *buf) { u16 p1 = SPI_LUT[v >> 4]; u16 p2 = SPI_LUT[v & 0x0F]; buf[0] = p1 >> 4; buf[1] = ((p1 & 0x0F) << 4) | (p2 >> 8); buf[2] = p2; } 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; // Prepend dummy 0x00 to absorb SPI hardware startup delay/glitch 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; // Ensure P2.3 (MOSI) and P2.5 (SCLK) are configured as push-pull output P2M1 &= ~((1 << 3) | (1 << 5)); P2M0 |= ((1 << 3) | (1 << 5)); SPSTAT = 0xC0; // Clear flags first SPDAT = b0; // Write data first! SPCTL = 0xD0; // Enable SPI after writing data. Should start shifting b0 immediately! // Unrolled 10-byte transmission with minimal gap (~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; // Disable SPI WS2812_DI = 0; MOTOR = 0; // Ensure motor is off EA = 1; } void WS2812_Reset(void) { SPCTL = 0x90; WS2812_DI = 0; { u8 i; for (i = 0; i < 10; i++) { Delay10us(); } } } void Delay_ms(u16 ms) { u16 i, j; for(i = 0; i < ms; i++) for(j = 12000; j > 0; j--); } void Delay10us(void) { unsigned char data i; _nop_(); i = 30; // 满足 24M 下时钟宽度 while(--i); } // 保证 16 位定时器 TH/TL 在读取时的原子性,防止在溢出瞬间读取出错 u16 GetTimer0_Safe(void) { u8 h1, l, h2; do { h1 = TH0; l = TL0; h2 = TH0; } while (h1 != h2); return ((u16)h1 << 8) | l; } void Delay_us(u16 us) { u16 ticks = (u16)((u32)us * (MAIN_Fosc / 1000000UL) / 12UL); TL0 = 0; TH0 = 0; TR0 = 1; // 启动 T0 计数器 while (GetTimer0_Safe() < ticks); TR0 = 0; // 停止计数 } /* ========================================================================= * STC32G 闪存 IAP (EEPROM) 读写逻辑 * ========================================================================= */ #define IAP_CMD_READ 1 #define IAP_CMD_WRITE 2 #define IAP_CMD_ERASE 3 // 关闭 IAP 功能,恢复 SFR 安全状态 void IAP_Disable(void) { IAP_CONTR = 0; IAP_CMD = 0; IAP_TRIG = 0; IAP_ADDRH = 0xff; IAP_ADDRL = 0xff; } // 从指定 IAP 地址读取一个字节 u8 IAP_ReadByte(u16 addr) { IAP_CONTR = 0x80; // 启用 IAP 功能 IAP_TPS = (u8)(MAIN_Fosc / 1000000UL); // 设置操作等待时钟参数 IAP_CMD = IAP_CMD_READ; IAP_ADDRL = (u8)addr; IAP_ADDRH = (u8)(addr >> 8); IAP_ADDRE = 0; // 高位物理地址清零 IAP_TRIG = 0x5a; // 发送硬件触发时序 IAP_TRIG = 0xa5; _nop_(); _nop_(); _nop_(); _nop_(); IAP_Disable(); return IAP_DATA; } // 往指定 IAP 地址写入一个字节 void IAP_WriteByte(u16 addr, u8 dat) { IAP_CONTR = 0x80; IAP_TPS = (u8)(MAIN_Fosc / 1000000UL); IAP_CMD = IAP_CMD_WRITE; IAP_ADDRL = (u8)addr; IAP_ADDRH = (u8)(addr >> 8); IAP_ADDRE = 0; IAP_DATA = dat; IAP_TRIG = 0x5a; IAP_TRIG = 0xa5; _nop_(); _nop_(); _nop_(); _nop_(); IAP_Disable(); } // 擦除指定地址所在的 512 字节 IAP 扇区 void IAP_EraseSector(u16 addr) { IAP_CONTR = 0x80; IAP_TPS = (u8)(MAIN_Fosc / 1000000UL); IAP_CMD = IAP_CMD_ERASE; IAP_ADDRL = (u8)addr; IAP_ADDRH = (u8)(addr >> 8); IAP_ADDRE = 0; IAP_TRIG = 0x5a; IAP_TRIG = 0xa5; _nop_(); _nop_(); _nop_(); _nop_(); IAP_Disable(); } // 从 IAP 的 Sector 0 载入配对列表数据 void Load_Database(void) { u16 addr = 0; u8 *ptr = (u8 *)&sensor_list; u16 size = sizeof(sensor_list); u16 i; for (i = 0; i < size; i++) { ptr[i] = IAP_ReadByte(addr++); } } // 将配对列表保存到 IAP 的 Sector 0 中 (先擦除再逐字节写入) void Save_Database(void) { u16 addr = 0; u8 *ptr = (u8 *)&sensor_list; u16 size = sizeof(sensor_list); u16 i; IAP_EraseSector(0); // 擦除物理 Sector 0 for (i = 0; i < size; i++) { IAP_WriteByte(addr++, ptr[i]); } } // 添加或覆盖传感器对码数据并自动存入 EEPROM void Add_Sensor(u32 addr, u8 type) { u8 i; u8 slot_to_use = 15; // 若槽位已满,默认覆盖最后一个位置 // 查找是否有空余位置,或者该 ID 已经配对过 for (i = 0; i < 16; i++) { if (sensor_list[i].is_used == 0x01) { u32 existing_addr = ((u32)sensor_list[i].addr[0] << 16) | ((u32)sensor_list[i].addr[1] << 8) | sensor_list[i].addr[2]; if (existing_addr == addr) { slot_to_use = i; break; } } else { slot_to_use = i; break; } } // 写入防区各项核心数据 sensor_list[slot_to_use].is_used = 0x01; sensor_list[slot_to_use].addr[0] = (u8)(addr >> 16); sensor_list[slot_to_use].addr[1] = (u8)(addr >> 8); sensor_list[slot_to_use].addr[2] = (u8)addr; sensor_list[slot_to_use].type = type; if (type < 5) { sensor_list[slot_to_use].zone = default_zones[type]; // 自动绑定普通或24h防区类型 // 绑定默认英文字符名 for (i = 0; i < 15; i++) { sensor_list[slot_to_use].name_gbk[i] = default_names[type][i]; if (default_names[type][i] == '\0') break; } sensor_list[slot_to_use].name_gbk[15] = '\0'; } Save_Database(); // 立即同步存盘 } // 检查某个接收到的 24 位地址是否已注册,若成功返回槽位索引 bit Check_Sensor_ID(u32 addr, u8 *out_slot_index) { u8 i; for (i = 0; i < 16; i++) { if (sensor_list[i].is_used == 0x01) { u32 slot_addr = ((u32)sensor_list[i].addr[0] << 16) | ((u32)sensor_list[i].addr[1] << 8) | sensor_list[i].addr[2]; if (slot_addr == addr) { *out_slot_index = i; return 1; // 匹配成功 } } } return 0; // 未在对码列表中找到 } /* ========================================================================= * 串口调试驱动 (用于捕获输出及测试打印) * ========================================================================= */ void Uart1_Init(void) { u16 reload = (u16)(65536UL - (MAIN_Fosc / 4 / 115200UL)); SCON = 0x50; // 8位可变波特率 AUXR |= 0x01; // 定时器2作为波特率发生器 AUXR |= 0x04; // 定时器2为 1T 模式 T2L = (u8)reload; T2H = (u8)(reload >> 8); AUXR |= 0x10; // 启动定时器2 TI = 0; } void Uart_SendByte(u8 dat) { REN = 0; SBUF = dat; while (!TI); TI = 0; RI = 0; REN = 1; } void Uart_SendString(char *s) { REN = 0; while (*s) { SBUF = *s++; while (!TI); TI = 0; } RI = 0; REN = 1; } char Uart_RxChar(void) { if (RI) { char c = SBUF; RI = 0; return c; } return 0; } void Uart_SendHex4(u8 val) { val &= 0x0F; if (val < 10) Uart_SendByte((u8)('0' + val)); else Uart_SendByte((u8)('A' + (val - 10))); } void Uart_SendHex8(u8 val) { Uart_SendHex4(val >> 4); Uart_SendHex4(val); } void Uart_SendHex20(u32 val) { Uart_SendHex4((u8)(val >> 16)); Uart_SendHex8((u8)(val >> 8)); Uart_SendHex8((u8)val); } void Uart_SendHex32(u32 val) { Uart_SendHex8((u8)(val >> 24)); Uart_SendHex8((u8)(val >> 16)); Uart_SendHex8((u8)(val >> 8)); Uart_SendHex8((u8)val); } void Uart_SendHex16(u16 val) { Uart_SendHex8((u8)(val >> 8)); Uart_SendHex8((u8)val); } void FormatHex(u32 val, char *buf) { u8 i; buf[0] = 'A'; buf[1] = 'D'; buf[2] = 'D'; buf[3] = 'R'; buf[4] = ':'; buf[5] = ' '; buf[6] = '0'; buf[7] = 'x'; for(i = 0; i < 5; i++) { u8 nibble = (val >> (4 * (4 - i))) & 0x0F; if(nibble < 10) buf[8 + i] = '0' + nibble; else buf[8 + i] = 'A' + (nibble - 10); } buf[13] = '\0'; } /* ========================================================================= * UI 页面渲染函数 * ========================================================================= */ void UI_ShowClockPage(SystemState state, u8 hour, u8 min) { char time_str[6]; LCD_Clear(COLOR_BLACK); // 右上角电量指示 (调整坐标防止贴在一起) LCD_DrawMonoBitmap(92, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK); LCD_ShowString(62, 24, "85%", COLOR_GRAY, COLOR_BLACK); // 2x 放大绘制当前时钟 (无显存双倍行/列插值算法) time_str[0] = '0' + (hour / 10); time_str[1] = '0' + (hour % 10); time_str[2] = ':'; time_str[3] = '0' + (min / 10); time_str[4] = '0' + (min % 10); time_str[5] = '\0'; LCD_ShowString16x32Centered(100, time_str, (state == STATE_ARMED) ? COLOR_WHITE : ((state == STATE_DISARMED) ? COLOR_WHITE : COLOR_CYAN), COLOR_BLACK); // 静态星期和日期 (法语 JEU) LCD_ShowStringCentered(155, "JEU 07-02", COLOR_GRAY, COLOR_BLACK); // 屏幕底端布撤防状态标识 (Y=202 避开屏幕下圆弧) if(state == STATE_ARMED) { LCD_DrawMonoBitmap(32, 202, 16, 16, bmp_lock_16x16, COLOR_RED, COLOR_BLACK); LCD_ShowString(52, 202, "ARME", COLOR_RED, COLOR_BLACK); } else if(state == STATE_DISARMED) { LCD_DrawMonoBitmap(22, 202, 16, 16, bmp_unlock_16x16, COLOR_GREEN, COLOR_BLACK); LCD_ShowString(42, 202, "DESARME", COLOR_GREEN, COLOR_BLACK); } } void UI_ShowPairMenuPage(u8 selected_index) { LCD_Clear(COLOR_BLACK); LCD_ShowStringCentered(30, "MENU APPAI.", COLOR_AMBER, COLOR_BLACK); // 绘制上一项 if (selected_index > 0) { LCD_ShowStringCentered(78, menu_items[selected_index - 1], COLOR_GRAY, COLOR_BLACK); } // 高亮框突出绘制当前选中的菜单项 LCD_DrawRectBorder(8, 110, 104, 28, COLOR_CYAN); LCD_ShowStringCentered(118, menu_items[selected_index], COLOR_CYAN, COLOR_BLACK); // 绘制下一项 if (selected_index < 4) { LCD_ShowStringCentered(158, menu_items[selected_index + 1], COLOR_GRAY, COLOR_BLACK); } } void UI_ShowPairWaitPage(u8 frame_index) { // 雷达扫描:仅局部擦除并重新绘制雷达波纹,消除整屏清屏带来的闪烁 if(frame_index == 0) LCD_DrawMonoBitmap(44, 56, 32, 32, bmp_radar_32x32_f1, COLOR_CYAN, COLOR_BLACK); else if(frame_index == 1) LCD_DrawMonoBitmap(44, 56, 32, 32, bmp_radar_32x32_f2, COLOR_CYAN, COLOR_BLACK); else LCD_DrawMonoBitmap(44, 56, 32, 32, bmp_radar_32x32_f3, COLOR_CYAN, COLOR_BLACK); } void UI_ShowPairConfirmPage(u32 addr) { char hex_str[15]; LCD_Clear(COLOR_BLACK); LCD_DrawRectBorder(4, 4, 112, 232, COLOR_GRAY); LCD_DrawMonoBitmap(44, 60, 32, 32, bmp_confirm_lock_32x32, COLOR_AMBER, COLOR_BLACK); LCD_ShowStringCentered(135, "CODE TROUVE", COLOR_WHITE, COLOR_BLACK); LCD_ShowStringCentered(160, "MAINTENIR SOS", COLOR_AMBER, COLOR_BLACK); FormatHex(addr, hex_str); LCD_ShowStringCentered(185, hex_str, COLOR_GRAY, COLOR_BLACK); } void UI_ShowPairSuccessPage(u32 addr) { char hex_str[15]; LCD_Clear(COLOR_BLACK); LCD_DrawMonoBitmap(44, 75, 32, 32, bmp_checkmark_32x32, COLOR_GREEN, COLOR_BLACK); LCD_ShowStringCentered(135, "SUCCES APPAI.", COLOR_GREEN, COLOR_BLACK); FormatHex(addr, hex_str); LCD_ShowStringCentered(165, hex_str, COLOR_GRAY, COLOR_BLACK); } void UI_ShowPairFailPage(u8 is_timeout) { LCD_Clear(COLOR_BLACK); LCD_DrawMonoBitmap(44, 75, 32, 32, bmp_cross_32x32, COLOR_RED, COLOR_BLACK); if (is_timeout) { LCD_ShowStringCentered(145, "DELAI DEPASSE", COLOR_RED, COLOR_BLACK); LCD_ShowStringCentered(170, "AUCUN SIGNAL", COLOR_GRAY, COLOR_BLACK); } else { LCD_ShowStringCentered(145, "ECHEC APPAI.", COLOR_RED, COLOR_BLACK); LCD_ShowStringCentered(170, "TYPE INCORRECT", COLOR_GRAY, COLOR_BLACK); } } void UI_ShowAlarmPage(char *sensor_name, u8 zone) { char zone_str[20]; LCD_Clear(COLOR_BLACK); LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED); LCD_DrawMonoBitmap(44, 55, 32, 32, bmp_door_32x32, COLOR_RED, COLOR_BLACK); LCD_ShowStringCentered(120, sensor_name, COLOR_RED, COLOR_BLACK); zone_str[0] = 'Z'; zone_str[1] = 'O'; zone_str[2] = 'N'; zone_str[3] = 'E'; zone_str[4] = ' '; zone_str[5] = '0' + zone; zone_str[6] = ' '; zone_str[7] = '|'; zone_str[8] = ' '; zone_str[9] = 'A'; zone_str[10] = 'L'; zone_str[11] = 'A'; zone_str[12] = 'R'; zone_str[13] = 'M'; zone_str[14] = 'E'; zone_str[15] = '\0'; LCD_ShowStringCentered(155, zone_str, COLOR_WHITE, COLOR_BLACK); } void UI_ShowSosPage(void) { LCD_Clear(COLOR_BLACK); LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED); LCD_DrawRectBorder(8, 8, 104, 224, COLOR_WHITE); LCD_DrawMonoBitmap(44, 55, 32, 32, bmp_siren_32x32, COLOR_RED, COLOR_BLACK); LCD_ShowStringCentered(125, "SOS EMIS", COLOR_RED, COLOR_BLACK); LCD_ShowStringCentered(155, "BRACELET ACTIF", COLOR_WHITE, COLOR_BLACK); } void UI_ShowBindingPage(void) { LCD_Clear(COLOR_BLACK); LCD_DrawRectBorder(4, 4, 112, 232, COLOR_CYAN); LCD_DrawMonoBitmap(44, 60, 32, 32, bmp_confirm_lock_32x32, COLOR_CYAN, COLOR_BLACK); LCD_ShowStringCentered(135, "LIAISON IPC", COLOR_WHITE, COLOR_BLACK); LCD_ShowStringCentered(160, "ENVOI EN COURS", COLOR_CYAN, COLOR_BLACK); } /* ========================================================================= * 定时器 1 (1ms 中断服务,包含消抖状态机) * ========================================================================= */ void Timer1_Init(void) { AUXR |= 0x40; // 1T 模式,不分频 TMOD &= 0x0F; // 16位自动重装载 { u16 reload = (u16)(65536UL - (MAIN_Fosc / 1000UL)); TL1 = (u8)reload; TH1 = (u8)(reload >> 8); } ET1 = 1; // 使使能中断 TR1 = 1; // 启动定时器 EA = 1; // 开启全局总中断 } // 1ms 时钟嘀嗒与按键扫描服务中断 void Timer1_Isr(void) interrupt 3 { // 1. 累加时间滴答并进位,维护软件RTC ms_tick++; if (ms_tick >= 1000) { ms_tick = 0; current_sec++; if (current_sec >= 60) { current_sec = 0; current_min++; if (current_min >= 60) { current_min = 0; current_hour++; if (current_hour >= 24) { current_hour = 0; } } clock_updated = 1; // 标记时钟更新,在主循环中更新屏幕 } } // 2. 雷达对码扫描倒计时 (30秒超时自动回弹待机) if (current_state == STATE_PAIR_WAIT) { pair_timeout_ms++; } // 3. 警报警示声光发生器逻辑 if (rgb_test_mode) { // RGB 测试模式下不更新虚拟 LED 状态,交由主循环串口命令控制 } else if (current_state == STATE_SOS_EMITTED) { // SOS 特殊告警:LED 红色极速闪烁 (5Hz),马达持续进行 1200ms 循环长振 u8 sos_flash = (ms_tick / 100) % 2; // 5Hz -> 100ms 翻转一次 LED_R = sos_flash ? 0 : 1; LED_G = 1; LED_B = 1; alarm_timer_ms++; if (alarm_timer_ms >= 1200) alarm_timer_ms = 0; if (alarm_timer_ms < 1000) MOTOR = 1; // 长振 1000ms else MOTOR = 0; // 停 200ms } else if (current_state == STATE_ALARM) { // 传感器告警模式:根据不同传感器类型执行专属灯光颜色与特定振动模式 u8 stype = sensor_list[alarm_sensor_slot].type; alarm_timer_ms++; if (alarm_timer_ms >= 5000) alarm_timer_ms = 0; // 5秒周期循环 if (stype == 0) // 门磁/窗磁:红色,1次短振 300ms { LED_R = 0; LED_G = 1; LED_B = 1; if (alarm_timer_ms < 300) MOTOR = 1; else MOTOR = 0; } else if (stype == 1) // 人体感应 PIR:黄色/橙色,2次短振 300ms (间隔 200ms) { LED_R = 0; LED_G = 0; LED_B = 1; if (alarm_timer_ms < 300) MOTOR = 1; else if (alarm_timer_ms >= 300 && alarm_timer_ms < 500) MOTOR = 0; else if (alarm_timer_ms >= 500 && alarm_timer_ms < 800) MOTOR = 1; else MOTOR = 0; } else if (stype == 2) // 烟雾传感器:绿色,3次短振 200ms (间隔 150ms) { LED_R = 1; LED_G = 0; LED_B = 1; if (alarm_timer_ms < 200) MOTOR = 1; else if (alarm_timer_ms >= 200 && alarm_timer_ms < 350) MOTOR = 0; else if (alarm_timer_ms >= 350 && alarm_timer_ms < 550) MOTOR = 1; else if (alarm_timer_ms >= 550 && alarm_timer_ms < 700) MOTOR = 0; else if (alarm_timer_ms >= 700 && alarm_timer_ms < 900) MOTOR = 1; else MOTOR = 0; } else if (stype == 3) // 气体传感器:紫色,4次短振 200ms (间隔 100ms) { LED_R = 0; LED_G = 1; LED_B = 0; if (alarm_timer_ms < 200) MOTOR = 1; else if (alarm_timer_ms >= 200 && alarm_timer_ms < 300) MOTOR = 0; else if (alarm_timer_ms >= 300 && alarm_timer_ms < 500) MOTOR = 1; else if (alarm_timer_ms >= 500 && alarm_timer_ms < 600) MOTOR = 0; else if (alarm_timer_ms >= 600 && alarm_timer_ms < 800) MOTOR = 1; else if (alarm_timer_ms >= 800 && alarm_timer_ms < 900) MOTOR = 0; else if (alarm_timer_ms >= 900 && alarm_timer_ms < 1100) MOTOR = 1; else MOTOR = 0; } else if (stype == 4) // 水浸传感器:黄色,2次长振 600ms (间隔 300ms) { LED_R = 0; LED_G = 0; LED_B = 1; if (alarm_timer_ms < 600) MOTOR = 1; else if (alarm_timer_ms >= 600 && alarm_timer_ms < 900) MOTOR = 0; else if (alarm_timer_ms >= 900 && alarm_timer_ms < 1500) MOTOR = 1; else MOTOR = 0; } else { // 其他未知类型默认红色闪烁 u8 flash = (ms_tick / 500) % 2; LED_R = flash ? 0 : 1; LED_G = 1; LED_B = 1; if (alarm_timer_ms < 300) MOTOR = 1; else MOTOR = 0; } } else if (current_state == STATE_PAIR_WAIT || current_state == STATE_PAIR_CONFIRM) { // 白色快闪 (3Hz): 166ms 翻转一次 (仅在搜索和确认时开启) u16 pair_flash_cnt = ms_tick % 333; if (pair_flash_cnt < 166) { LED_R = 0; LED_G = 0; LED_B = 0; // 白色 (R+G+B 开启) } else { LED_R = 1; LED_G = 1; LED_B = 1; // 熄灭 } MOTOR = 0; } else { MOTOR = 0; LED_R = 1; LED_G = 1; LED_B = 1; alarm_flash_flag = 0; alarm_timer_ms = 0; motor_timer_ms = 0; } // 4. 按键防抖与时间累加 (每 10ms 进行一次逻辑检测) key_scan_timer++; if (key_scan_timer >= 10) { // 物理引脚低电平有效,转换成逻辑高有效状态进行判定 (用 u8 代替 bit 作为局部变量,在块开头声明变量以符合 C90 规范) u8 raw_up = !KEY_UP; u8 raw_down = !KEY_DOWN; u8 raw_sos = !KEY_SOS; key_scan_timer = 0; // 组合键检测:UP+DOWN 同时长按 3 秒 (300 * 10ms = 3000ms) if (raw_up && raw_down) { comb_hold++; if (comb_hold == 300) { key_event_buf = KEY_EVENT_UP_DOWN_COMB; } key_up_hold = 0; key_down_hold = 0; } else { comb_hold = 0; // 检测上键 UP if (raw_up) { key_up_hold++; if (key_up_hold == 300) // 达到 3.0 秒触发长按事件 { key_event_buf = KEY_EVENT_UP_LONG; } } else { if (key_up_hold >= 2 && key_up_hold < 300) // 抬手时判定为单击事件 { key_event_buf = KEY_EVENT_UP_CLICK; } key_up_hold = 0; } // 检测下键 DOWN if (raw_down) { key_down_hold++; if (key_down_hold == 300) // 达到 3.0 秒触发长按事件 { key_event_buf = KEY_EVENT_DOWN_LONG; } } else { if (key_down_hold >= 2 && key_down_hold < 300) // 抬手时判定为单击事件 { key_event_buf = KEY_EVENT_DOWN_CLICK; } key_down_hold = 0; } // 检测紧急 SOS 键 if (raw_sos) { key_sos_hold++; if (key_sos_hold == 300) // 长按 3.0 秒 { // 在对码确认状态下,长按 3 秒即可触发保存 if (current_state == STATE_PAIR_CONFIRM) { key_event_buf = KEY_EVENT_SOS_LONG; } } else if (key_sos_hold == 500) // 长按 5.0 秒 { // 在常态待机防区下,长按 5 秒触发求救发射 if (current_state == STATE_NORMAL || current_state == STATE_ARMED || current_state == STATE_DISARMED) { key_event_buf = KEY_EVENT_SOS_LONG; } } } else { if (key_sos_hold >= 2 && key_sos_hold < 300) // 抬手时判定为短按事件 { key_event_buf = KEY_EVENT_SOS_CLICK; } key_sos_hold = 0; } } } // 5. WS2812B 实际硬件驱动刷新 (当虚拟 LED 寄存器发生变化时) if (LED_R != last_hw_r || LED_G != last_hw_g || LED_B != last_hw_b) { last_hw_r = LED_R; last_hw_g = LED_G; last_hw_b = LED_B; WS2812_Write24Bit(LED_G ? 0 : 255, LED_R ? 0 : 255, LED_B ? 0 : 255); WS2812_Reset(); } } /* ========================================================================= * 系统主循环逻辑 (交互状态机与射频匹配核心) * ========================================================================= */ void main(void) { KeyEvent ev; u8 state_changed = 0; // 用 u8 代替 bit 变量 u8 last_radar_sec = 99; u8 last_led_r = 1; u8 last_led_g = 1; u8 last_led_b = 1; u8 last_motor = 0; char cmd; // 单片机时钟与看门狗基础初始化 WTST = 0; EAXFR = 1; CKCON = 0; WDT_CONTR = 0x00; // 外设 GPIO 及射频接口引脚初始化 GPIO_Init(); RF_Init(); Delay_ms(500); // 唤醒 AMOLED 屏幕及供电调频芯片 SGM_SendPulse(27); Delay_ms(50); // 初始化显示屏驱动与命令 LCD_Init(); // 配置 Uart 用于后台诊断输出 Uart1_Init(); Uart_SendString("Wristband System Initialized!\r\n"); // 读入掉电保存的对码表数据,并启动 1ms 中断调度引擎 Load_Database(); Timer1_Init(); // 默认进入 NORMAL 待机模式,显示时钟,并将射频调制芯片置为被动接收模式 current_state = STATE_NORMAL; UI_ShowClockPage(current_state, current_hour, current_min); RF_SetMode(1); // 开接收天线 while(1) { // 串口调试与物理引脚/器件仿真输入 cmd = Uart_RxChar(); if (cmd != '\0') { if (cmd == 'u') { key_event_buf = KEY_EVENT_UP_CLICK; Uart_SendString("[UART SIM] KEY_UP Clicked\r\n"); } else if (cmd == 'U') { key_event_buf = KEY_EVENT_UP_LONG; Uart_SendString("[UART SIM] KEY_UP Long Pressed\r\n"); } else if (cmd == 'd') { key_event_buf = KEY_EVENT_DOWN_CLICK; Uart_SendString("[UART SIM] KEY_DOWN Clicked\r\n"); } else if (cmd == 'D') { key_event_buf = KEY_EVENT_DOWN_LONG; Uart_SendString("[UART SIM] KEY_DOWN Long Pressed\r\n"); } else if (cmd == 's') { key_event_buf = KEY_EVENT_SOS_CLICK; Uart_SendString("[UART SIM] KEY_SOS Clicked\r\n"); } else if (cmd == 'S') { key_event_buf = KEY_EVENT_SOS_LONG; Uart_SendString("[UART SIM] KEY_SOS Long Pressed\r\n"); } else if (cmd == 'c' || cmd == 'C') { key_event_buf = KEY_EVENT_UP_DOWN_COMB; Uart_SendString("[UART SIM] KEY_UP + KEY_DOWN Combined\r\n"); } else if (cmd == 'a' || cmd == 'A') { u32 mock_addr = 0x123456; u8 mock_slot; if (!Check_Sensor_ID(mock_addr, &mock_slot)) { Add_Sensor(mock_addr, 0); // 0: 门磁 } captured_addr = mock_addr; current_state = STATE_ALARM; state_changed = 1; Uart_SendString("[UART SIM] Mock RF Alarm: ADDR 0x123456\r\n"); } else if (cmd == 'p' || cmd == 'P') { if (current_state == STATE_PAIR_WAIT) { captured_addr = 0x789ABC; captured_type = menu_select; current_state = STATE_PAIR_CONFIRM; state_changed = 1; Uart_SendString("[UART SIM] Mock RF Pair Signal: ADDR 0x789ABC\r\n"); } else { Uart_SendString("[UART SIM] Ignore: Not in PAIR WAIT state\r\n"); } } else if (cmd == 't' || cmd == 'T') { Uart_SendString("[UART SIM] SPI 3MHz Clock Test on P2.5 (SCLK) and P2.3 (MOSI) active. Press reset to exit.\r\n"); // Configure SCLK (P2.5) and MOSI (P2.3) as push-pull output P2M1 &= ~((1 << 3) | (1 << 5)); P2M0 |= ((1 << 3) | (1 << 5)); SPCTL = 0xD0; // SPI Master, 6.0 MHz (SYSCLK / 4) while(1) { SPSTAT = 0xC0; SPDAT = 0xAA; while (!(SPSTAT & 0x80)); } } else if (cmd == '1') { current_state = STATE_NORMAL; state_changed = 1; Uart_SendString("[UART SIM] Set State to: NORMAL (Standby)\r\n"); } else if (cmd == '2') { current_state = STATE_ARMED; state_changed = 1; Uart_SendString("[UART SIM] Set State to: ARMED (Armed)\r\n"); } else if (cmd == '3') { current_state = STATE_DISARMED; state_changed = 1; Uart_SendString("[UART SIM] Set State to: DISARMED (Disarmed)\r\n"); } else if (cmd == '4') { rgb_test_mode = 1; LED_R = 0; LED_G = 1; LED_B = 1; // 红色亮 (0代表亮) Uart_SendString("[UART SIM] RGB Test -> RED\r\n"); } else if (cmd == '5') { rgb_test_mode = 1; LED_R = 1; LED_G = 0; LED_B = 1; // 绿色亮 Uart_SendString("[UART SIM] RGB Test -> GREEN\r\n"); } else if (cmd == '6') { rgb_test_mode = 1; LED_R = 1; LED_G = 1; LED_B = 0; // 蓝色亮 Uart_SendString("[UART SIM] RGB Test -> BLUE\r\n"); } else if (cmd == '7') { rgb_test_mode = 1; LED_R = 0; LED_G = 0; LED_B = 1; // 黄色亮 (红+绿) Uart_SendString("[UART SIM] RGB Test -> YELLOW\r\n"); } else if (cmd == '8') { rgb_test_mode = 1; LED_R = 0; LED_G = 1; LED_B = 0; // 紫色亮 (红+蓝) Uart_SendString("[UART SIM] RGB Test -> PURPLE\r\n"); } else if (cmd == '9') { rgb_test_mode = 1; LED_R = 1; LED_G = 0; LED_B = 0; // 青色亮 (绿+蓝) Uart_SendString("[UART SIM] RGB Test -> CYAN\r\n"); } else if (cmd == '0') { rgb_test_mode = 1; LED_R = 0; LED_G = 0; LED_B = 0; // 白色亮 (红+绿+蓝) Uart_SendString("[UART SIM] RGB Test -> WHITE\r\n"); } else if (cmd == 'f' || cmd == 'F') { rgb_test_mode = 0; LED_R = 1; LED_G = 1; LED_B = 1; // 熄灭 Uart_SendString("[UART SIM] RGB Test -> OFF (Normal Mode)\r\n"); } } // 1. 读取按键事件并自动清空 ev = key_event_buf; key_event_buf = KEY_EVENT_NONE; if (ev != KEY_EVENT_NONE) { rgb_test_mode = 0; // 任何物理/按键事件触发时退出 RGB 测试模式 // 通过串口打印获取到的按键事件代号进行测试联调 Uart_SendString("Key Event Captured: "); Uart_SendHex8((u8)ev); Uart_SendString("\r\n"); // 根据不同的系统当前状态,执行状态迁移逻辑 if (current_state == STATE_NORMAL || current_state == STATE_ARMED || current_state == STATE_DISARMED) { if (ev == KEY_EVENT_UP_DOWN_COMB) // 同时长按 UP + DOWN 3 秒进入配对菜单 { current_state = STATE_PAIR_MENU; menu_select = 0; state_changed = 1; } else if (ev == KEY_EVENT_SOS_CLICK) // 短按 SOS 发射 SOS 报警 { current_state = STATE_SOS_EMITTED; state_changed = 1; } else if (ev == KEY_EVENT_SOS_LONG) // 长按 SOS 5 秒与 IPC 绑定 { UI_ShowBindingPage(); RF_SetMode(2); // TX mode EV1527_Transmit(CLONED_ADDR, 0x01); // 对码绑定电报数据为 0x01 RF_SetMode(0); // Idle Delay_ms(2000); // 维持 2 秒 current_state = STATE_NORMAL; state_changed = 1; } } else if (current_state == STATE_PAIR_MENU) { if (ev == KEY_EVENT_UP_CLICK) // 菜单选择上移 { if (menu_select > 0) { menu_select--; state_changed = 1; } } else if (ev == KEY_EVENT_DOWN_CLICK) // 菜单选择下移 { if (menu_select < 4) { menu_select++; state_changed = 1; } } else if (ev == KEY_EVENT_SOS_CLICK) // 单击 SOS 确认选项,进入对码搜索并触发 100ms 短振与白灯快闪 { MOTOR = 1; Delay_ms(100); MOTOR = 0; current_state = STATE_PAIR_WAIT; pair_timeout_ms = 0; // 重置对码超时计时器 state_changed = 1; } else if (ev == KEY_EVENT_DOWN_LONG) // 长按 DOWN 键 3 秒强行返回待机 { current_state = STATE_NORMAL; state_changed = 1; } } else if (current_state == STATE_PAIR_WAIT) { if (ev == KEY_EVENT_DOWN_LONG) // 在雷达页面,长按 DOWN 3秒强行退出 { current_state = STATE_NORMAL; state_changed = 1; } } else if (current_state == STATE_PAIR_CONFIRM) { if (ev == KEY_EVENT_SOS_LONG) // 在确认页面,长按 SOS 3 秒保存对码结果 { Add_Sensor(captured_addr, captured_type); current_state = STATE_PAIR_SUCCESS; state_changed = 1; } else if (ev == KEY_EVENT_DOWN_LONG) // 在确认页面,长按 DOWN 3 秒放弃保存返回待机 { current_state = STATE_NORMAL; state_changed = 1; } } else if (current_state == STATE_ALARM) { // 在防区报警闪烁状态下,短按任意物理按键均可清除报警声光 current_state = STATE_NORMAL; state_changed = 1; } else if (current_state == STATE_SOS_EMITTED) { // 再次长按任意物理按键即可主动解除求救模式 if (ev == KEY_EVENT_SOS_LONG || ev == KEY_EVENT_UP_LONG || ev == KEY_EVENT_DOWN_LONG) { current_state = STATE_NORMAL; state_changed = 1; } } } // 2. 对码雷达扫描 30 秒超时自动跳回时钟主界面检测 if (current_state == STATE_PAIR_WAIT && pair_timeout_ms >= 30000UL) { pair_timeout_ms = 0; UI_ShowPairFailPage(1); // 调用 Fail 绘制接口并传入超时标志 1 Delay_ms(2500); // 维持 2.5 秒超时警告 current_state = STATE_NORMAL; state_changed = 1; } // 3. 状态切换的屏幕重写渲染 (只有发生状态改变才清屏,杜绝频闪) if (state_changed) { state_changed = 0; // 仅在此处清除状态改变标记,确保异步状态转移时屏幕能被正确重绘 // 通过串口反馈状态机重绘过程 Uart_SendString("State Transition to: "); Uart_SendHex8((u8)current_state); Uart_SendString("\r\n"); if (current_state == STATE_NORMAL || current_state == STATE_ARMED || current_state == STATE_DISARMED) { RF_SetMode(1); // 切回接收模式监听防区 UI_ShowClockPage(current_state, current_hour, current_min); } else if (current_state == STATE_PAIR_MENU) { RF_SetMode(0); // 关闭射频节省能量 UI_ShowPairMenuPage(menu_select); } else if (current_state == STATE_PAIR_WAIT) { RF_SetMode(1); // 开启射频解调芯片,开始抓包 LCD_Clear(COLOR_BLACK); LCD_ShowStringCentered(135, "RECHERCHE...", COLOR_WHITE, COLOR_BLACK); LCD_ShowStringCentered(160, "DECLENCH. CAPT", COLOR_CYAN, COLOR_BLACK); UI_ShowPairWaitPage(0); last_radar_sec = 99; // 强行重置雷达波纹帧计数器 } else if (current_state == STATE_PAIR_CONFIRM) { RF_SetMode(0); // 捕获成功,关闭射频 UI_ShowPairConfirmPage(captured_addr); } else if (current_state == STATE_PAIR_SUCCESS) { RF_SetMode(0); UI_ShowPairSuccessPage(captured_addr); // 触发对码成功物理反馈:强振 1 次 (400ms),LED 绿色常亮 2 秒 MOTOR = 1; LED_G = 0; // 开启绿灯 LED_R = 1; LED_B = 1; Delay_ms(400); // 振动 400ms MOTOR = 0; // 停止振动 Delay_ms(1600); // 维持绿灯常亮累计满 2 秒 (400 + 1600 = 2000ms) LED_G = 1; // 熄灭绿灯 Delay_ms(500); // 补齐页面显示总时间 2.5 秒 (2000 + 500 = 2500ms) current_state = STATE_NORMAL; UI_ShowClockPage(current_state, current_hour, current_min); RF_SetMode(1); } else if (current_state == STATE_ALARM) { u8 slot; char *name = "UNKNOWN SENSOR"; if (Check_Sensor_ID(captured_addr, &slot)) { name = sensor_list[slot].name_gbk; // 获取对应的注册英文名字 alarm_sensor_slot = slot; } UI_ShowAlarmPage(name, 1); } else if (current_state == STATE_SOS_EMITTED) { UI_ShowSosPage(); } } // 4. 定期局部刷新、动画更新与射频解调轮询 if (current_state == STATE_NORMAL || current_state == STATE_ARMED || current_state == STATE_DISARMED) { // 时钟分钟数字局部刷新 (防闪烁) if (clock_updated) { clock_updated = 0; UI_ShowClockPage(current_state, current_hour, current_min); } // 监听并解析防区发射的信号码 { u32 rx_addr; u8 rx_data; if (EV1527_Decode(&rx_addr, &rx_data)) { u8 slot; if (Check_Sensor_ID(rx_addr, &slot)) // 检查接收 of 地址是否在配对列表中 { u8 sensor_type = sensor_list[slot].type; if (sensor_type < 5) // 仅触发普通防区传感器,彻底过滤并排除SOS信号接收 { // 24小时防区 (zone==0) 任何时候都触发,普通防区 (zone==1) 仅在 ARMED 状态下触发 if (sensor_list[slot].zone == 0 || current_state == STATE_ARMED) { captured_addr = rx_addr; current_state = STATE_ALARM; state_changed = 1; } } } } } } else if (current_state == STATE_PAIR_WAIT) { // 雷达搜索页面每 250ms 局部刷新一帧雷达天线波纹 u8 frame = (u8)((ms_tick / 250) % 3); if (frame != last_radar_sec) { last_radar_sec = frame; UI_ShowPairWaitPage(frame); } // 在对码搜索状态下监听任意 EV1527 无线电码 { u32 rx_addr; u8 rx_data; if (EV1527_Decode(&rx_addr, &rx_data)) { captured_addr = rx_addr; captured_type = menu_select; current_state = STATE_PAIR_CONFIRM; // 捕获到信号,移至确认页 state_changed = 1; } } } else if (current_state == STATE_SOS_EMITTED) { // 主动 SOS 求救状态下,每 500ms 通过 LT4455 发射一次射频求救帧 u8 sec_phase = (u8)((ms_tick / 500) % 2); if (sec_phase != last_radar_sec) { last_radar_sec = sec_phase; RF_SetMode(2); // 射频置为发射端模式 EV1527_Transmit(CLONED_ADDR, 0x08); // 发射手环自带地址 CLONED_ADDR 且数据为 0x08 RF_SetMode(0); // 发射完成复位,关闭发射机 } // 双实线红色警告边框的闪烁效果 if (alarm_flash_flag) { LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED); LCD_DrawRectBorder(8, 8, 104, 224, COLOR_WHITE); } else { LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK); LCD_DrawRectBorder(8, 8, 104, 224, COLOR_BLACK); } } else if (current_state == STATE_ALARM) { // 警报闪烁状态下,交替绘制红色和黑色边框 if (alarm_flash_flag) { LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED); } else { LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK); } } // 仿真 LED/马达状态串口输出 if (LED_R != last_led_r || LED_G != last_led_g || LED_B != last_led_b) { last_led_r = LED_R; last_led_g = LED_G; last_led_b = LED_B; Uart_SendString("[STATE] LED status -> R:"); Uart_SendByte(last_led_r ? '0' : '1'); Uart_SendString(" G:"); Uart_SendByte(last_led_g ? '0' : '1'); Uart_SendString(" B:"); Uart_SendByte(last_led_b ? '0' : '1'); Uart_SendString("\r\n"); } if (MOTOR != last_motor) { last_motor = MOTOR; Uart_SendString("[STATE] MOTOR status -> "); if (last_motor) { Uart_SendString("VIBRATING (ON)\r\n"); } else { Uart_SendString("SILENT (OFF)\r\n"); } } } } // 芯片基础 IO 端口属性定义 void GPIO_Init(void) { IE = 0x00; IE2 = 0x00; TCON = 0x00; TMOD &= 0xF0; // T0, T1 为模式 0 (16位自动重装载) TR0 = 0; ET0 = 0; AUXR = 0x00; // T0, T1 为 12T 模式 (默认) INTCLKO = 0x00; P_SW1 = 0x04; // 串口引脚映射:P3.0 RxD, P3.1 TxD; SPI映射到第二组 (P2.2-P2.5) P_SW2 = 0x00; P_SW3 = 0x00; // 配置 P0.1 (KEY_UP), P0.2 (KEY_SOS), P0.3 (KEY_DOWN) 为双向输入口 P0M1 &= ~((1 << 1) | (1 << 2) | (1 << 3)); P0M0 &= ~((1 << 1) | (1 << 2) | (1 << 3)); // 配置 P2.3 (WS2812_DI) 为推挽输出,初始化默认输出 0 (Reset/Idle) P2M1 &= ~(1 << 3); P2M0 |= (1 << 3); WS2812_DI = 0; // 配置 P2.5 (MOTOR) 震动马达、P2.6 (LED_B)、P2.7 (LED_G) 为推挽输出 P2M1 &= ~((1 << 5) | (1 << 6) | (1 << 7)); P2M0 |= ((1 << 5) | (1 << 6) | (1 << 7)); // 初始化虚拟 LED 与跟踪变量为熄灭状态 (1代表灭) LED_R = 1; LED_G = 1; LED_B = 1; last_hw_r = 1; last_hw_g = 1; last_hw_b = 1; MOTOR = 0; // 默认马达静止 // 初始化 WS2812 灯珠为熄灭状态 (0, 0, 0) WS2812_Write24Bit(0, 0, 0); WS2812_Reset(); // 配置 P3.4 (SGM_CTRL) 为推挽输出,P3.1 (TxD) 为推挽输出,P3.0 (RxD) 为双向口输入 P3M1 &= ~((1 << 0) | (1 << 1) | (1 << 4)); P3M0 &= ~(1 << 0); P3M0 |= ((1 << 1) | (1 << 4)); }