修正1.14寸屏幕垂直偏置并添加自动清屏以清除开机噪声;修正新硬件射频收发引脚对调,低功耗唤醒中断重定向至P3.6中断16;添加一键串口收发诊断测试指令,并临时屏蔽SOS物理按键
This commit is contained in:
@@ -10,10 +10,6 @@
|
||||
|
||||
// 外部引用的全局系统状态变量
|
||||
extern SystemState current_state;
|
||||
extern u8 current_hour;
|
||||
extern u8 current_min;
|
||||
extern u8 current_sec;
|
||||
extern volatile u8 clock_updated;
|
||||
extern volatile u16 ms_tick;
|
||||
|
||||
// 待机时钟应用内特有的编辑时间私有变量
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include "event.h"
|
||||
#include "system.h"
|
||||
#include "database.h"
|
||||
#include "clock.h"
|
||||
#include "../Drivers/rf.h"
|
||||
|
||||
// 外部全局变量引用
|
||||
extern SystemState current_state;
|
||||
extern u8 current_sec;
|
||||
extern u8 captured_type;
|
||||
extern u32 captured_addr;
|
||||
extern volatile u16 ms_tick;
|
||||
|
||||
27
App/config.h
27
App/config.h
@@ -22,19 +22,19 @@ sbit KEY_DOWN = P0^3;
|
||||
sbit KEY_SOS = P2^6;
|
||||
// FCOB 幻彩灯条 DIN 数据控制线
|
||||
sbit RGB_DIN = P2^3;
|
||||
// LR690L 射频芯片休眠/工作控制引脚 (低电平使能开启工作)
|
||||
sbit SHUT = P2^2;
|
||||
// SGM3833 PMIC 屏幕负压供电使能脚 (1使能,0关闭)
|
||||
sbit SGM_CTRL = P3^4;
|
||||
// Truly AMOLED 屏幕复位脚 (RESET),低电平复位
|
||||
// LR690L 射频芯片休眠/工作控制引脚 (0:开启工作, 1:关闭休眠)
|
||||
sbit SHUT = P3^5;
|
||||
// LHS114TC-IF03 屏幕 LEDA 白色背光开启引脚 (1点亮,0熄灭)
|
||||
sbit SGM_CTRL = P1^7;
|
||||
// LHS114TC-IF03 屏幕复位脚 (RESET),低电平复位
|
||||
sbit LCD_RST = P1^0;
|
||||
// Truly AMOLED 屏幕数据/指令选择脚 (D/C,1:数据, 0:命令)
|
||||
// LHS114TC-IF03 屏幕数据/指令选择脚 (D/C,1:数据, 0:命令)
|
||||
sbit LCD_DCX = P1^1;
|
||||
// Truly AMOLED 屏幕 SPI 数据脚 (MOSI/SDA)
|
||||
// LHS114TC-IF03 屏幕 SPI 数据脚 (MOSI/SDA)
|
||||
sbit LCD_SDI = P1^4;
|
||||
// Truly AMOLED 屏幕 SPI 时钟脚 (SCLK)
|
||||
// LHS114TC-IF03 屏幕 SPI 时钟脚 (SCLK)
|
||||
sbit LCD_SCL = P1^5;
|
||||
// Truly AMOLED 屏幕 SPI 片选脚 (CS),低电平有效
|
||||
// LHS114TC-IF03 屏幕 SPI 片选脚 (CS),低电平有效
|
||||
sbit LCD_CS = P1^6;
|
||||
|
||||
/* ====== 系统运行状态枚举 ====== */
|
||||
@@ -68,9 +68,18 @@ typedef enum {
|
||||
KEY_EVENT_CONFIRM_LONG // ■ 确认键长按事件 (打开主菜单)
|
||||
} KeyEvent;
|
||||
|
||||
/* ====== 事件优先级枚举 ====== */
|
||||
typedef enum {
|
||||
EVENT_PRIORITY_LOW, // 0: 低优先级:系统内部事件,如定时更新
|
||||
EVENT_PRIORITY_NORMAL, // 1: 正常优先级:大部分用户交互事件
|
||||
EVENT_PRIORITY_HIGH, // 2: 高优先级:报警相关事件,插队到队首
|
||||
EVENT_PRIORITY_URGENT // 3: 紧急优先级:SOS等,插队到队首
|
||||
} EventPriority;
|
||||
|
||||
/* ====== 系统事件结构体定义 ====== */
|
||||
typedef struct {
|
||||
KeyEvent key_event; // 关联的按键事件类型
|
||||
EventPriority priority; // 事件优先级
|
||||
u32 extra_data; // 随事件携带的额外数据 (如 24 位射频源地址等)
|
||||
u8 extra_size; // 额外数据的有效字节大小 (0~4)
|
||||
} SystemEvent;
|
||||
|
||||
@@ -173,7 +173,7 @@ void Timer1_Isr(void) interrupt 3
|
||||
u8 raw_up = !KEY_UP;
|
||||
u8 raw_down = !KEY_DOWN;
|
||||
u8 raw_confirm = !KEY_CONFIRM;
|
||||
u8 raw_sos = !KEY_SOS;
|
||||
u8 raw_sos = 0; // 临时注释关闭 SOS 物理按键电平检测,防浮空干扰
|
||||
key_scan_timer = 0; // 重置扫描分频计数器
|
||||
|
||||
// 检测到有任意按键处于下压状态,立即将无操作闲置休眠计时器归零
|
||||
@@ -249,6 +249,7 @@ void Timer1_Isr(void) interrupt 3
|
||||
key_confirm_hold = 0; // 释放归零
|
||||
}
|
||||
|
||||
/*
|
||||
// SOS 物理求救按键状态机
|
||||
if (raw_sos) {
|
||||
key_sos_hold++;
|
||||
@@ -263,6 +264,7 @@ void Timer1_Isr(void) interrupt 3
|
||||
}
|
||||
key_sos_hold = 0; // 释放归零
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
115
App/main.c
115
App/main.c
@@ -5,21 +5,15 @@
|
||||
#include "database.h"
|
||||
#include "ui.h"
|
||||
#include "system.h"
|
||||
#include "clock.h"
|
||||
#include "xtell.h"
|
||||
#include "../Drivers/rf.h"
|
||||
#include "../Drivers/lcd.h"
|
||||
|
||||
// 声明外部射频模拟变量
|
||||
extern volatile u32 mock_rx_addr;
|
||||
extern volatile u8 mock_rx_data;
|
||||
extern volatile bit mock_rf_ready;
|
||||
|
||||
/* =========================================================================
|
||||
* 系统全局变量定义
|
||||
* ========================================================================= */
|
||||
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默认为正常时钟待机页
|
||||
|
||||
|
||||
u8 menu_select = 0; // 主菜单当前选中的行高亮索引 (0~2)
|
||||
u32 captured_addr = 0; // 配对或报警时,捕获到的传感器 24 位 EV1527 射频物理地址
|
||||
u8 captured_type = 0; // 正在对码或触发警报的传感器设备类型 (0:门磁, 1:PIR...)
|
||||
@@ -49,6 +43,17 @@ volatile u16 comb_hold = 0; // ▲ + ▼ 组合键按下时长累
|
||||
* ========================================================================= */
|
||||
/**
|
||||
* @brief 解析通过串口 1 发送来的键盘及测试模拟指令
|
||||
* @param cmd 接收到的 ASCII 字符命令
|
||||
* @details 负责将字符指令转化对应的系统按键或射频事件,并推入事件队列以测试软件架构:
|
||||
* - 'u'/'U': 模拟短按/长按 ▲ 键。
|
||||
* - 'd'/'D': 模拟短按/长按 ▼ 键。
|
||||
* - 's'/'S': 模拟短按/长按 SOS 物理键(优先插入队首)。
|
||||
* - 'c'/'C': 模拟组合键触发。
|
||||
* - 'a'/'A': 模拟无线传感器入侵触发警报信号,地址固定为 0x123456,zone=1。
|
||||
* - 'p'/'P': 模拟对码期间捕获的 24 位无线对码信号,地址固定为 0x789ABC。
|
||||
* - '1'/'2'/'3': 模拟系统的正常、已布防、已撤防状态切换。
|
||||
* - 'z'/'Z': 模拟超时,强行使闲置计数器置 6000,触发自动深度休眠。
|
||||
* - 't'/'T': 触发屏幕与无线控制引脚测试。
|
||||
*/
|
||||
void Debug_ProcessCommand(char cmd)
|
||||
{
|
||||
@@ -59,32 +64,39 @@ void Debug_ProcessCommand(char cmd)
|
||||
|
||||
if (cmd == 'u') {
|
||||
debug_evt.key_event = KEY_EVENT_UP_CLICK;
|
||||
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(debug_evt); // 压入队尾
|
||||
XTELL_LOG("[UART] KEY_UP Clicked\r\n");
|
||||
Uart_SendString("[UART] KEY_UP Clicked\r\n");
|
||||
} else if (cmd == 'U') {
|
||||
debug_evt.key_event = KEY_EVENT_UP_LONG;
|
||||
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(debug_evt);
|
||||
XTELL_LOG("[UART] KEY_UP Long Pressed\r\n");
|
||||
Uart_SendString("[UART] KEY_UP Long Pressed\r\n");
|
||||
} else if (cmd == 'd') {
|
||||
debug_evt.key_event = KEY_EVENT_DOWN_CLICK;
|
||||
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(debug_evt);
|
||||
XTELL_LOG("[UART] KEY_DOWN Clicked\r\n");
|
||||
Uart_SendString("[UART] KEY_DOWN Clicked\r\n");
|
||||
} else if (cmd == 'D') {
|
||||
debug_evt.key_event = KEY_EVENT_DOWN_LONG;
|
||||
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(debug_evt);
|
||||
XTELL_LOG("[UART] KEY_DOWN Long Pressed\r\n");
|
||||
Uart_SendString("[UART] KEY_DOWN Long Pressed\r\n");
|
||||
} else if (cmd == 's') {
|
||||
debug_evt.key_event = KEY_EVENT_SOS_CLICK;
|
||||
debug_evt.priority = EVENT_PRIORITY_URGENT;
|
||||
EventQueue_InsertFront(debug_evt); // 紧急事件插入队首
|
||||
XTELL_LOG("[UART] KEY_SOS Clicked\r\n");
|
||||
Uart_SendString("[UART] KEY_SOS Clicked\r\n");
|
||||
} else if (cmd == 'S') {
|
||||
debug_evt.key_event = KEY_EVENT_SOS_LONG;
|
||||
debug_evt.priority = EVENT_PRIORITY_URGENT;
|
||||
EventQueue_InsertFront(debug_evt);
|
||||
XTELL_LOG("[UART] KEY_SOS Long Pressed\r\n");
|
||||
Uart_SendString("[UART] KEY_SOS Long Pressed\r\n");
|
||||
} else if (cmd == 'c' || cmd == 'C') {
|
||||
debug_evt.key_event = KEY_EVENT_UP_DOWN_COMB;
|
||||
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(debug_evt);
|
||||
XTELL_LOG("[UART] KEY_UP+DOWN Combined\r\n");
|
||||
Uart_SendString("[UART] KEY_UP+DOWN Combined\r\n");
|
||||
} else if (cmd == 'a' || cmd == 'A') {
|
||||
u32 mock_addr = 0x123456; // 设定模拟的报警射频源地址
|
||||
u8 mock_slot;
|
||||
@@ -92,42 +104,52 @@ void Debug_ProcessCommand(char cmd)
|
||||
if (!Check_Sensor_ID(mock_addr, &mock_slot)) {
|
||||
Add_Sensor_With_Zone(mock_addr, 0, 1);
|
||||
}
|
||||
mock_rx_addr = mock_addr;
|
||||
mock_rx_data = 0x01;
|
||||
mock_rf_ready = 1; // 触发射频模拟
|
||||
XTELL_LOG("[UART] Mock RF Alarm Triggered\r\n");
|
||||
debug_evt.key_event = KEY_EVENT_NONE;
|
||||
debug_evt.priority = EVENT_PRIORITY_HIGH; // 入侵报警设为 HIGH 优先级
|
||||
debug_evt.extra_data = mock_addr;
|
||||
debug_evt.extra_size = 4;
|
||||
EventQueue_InsertFront(debug_evt); // 高优先级插队
|
||||
Uart_SendString("[UART] Mock RF Alarm\r\n");
|
||||
} else if (cmd == 'p' || cmd == 'P') {
|
||||
mock_rx_addr = 0x789ABC;
|
||||
mock_rx_data = 0x01;
|
||||
mock_rf_ready = 1; // 触发射频模拟
|
||||
XTELL_LOG("[UART] Mock RF Pair Triggered\r\n");
|
||||
// 只有当手环切入 Pair 模式时,模拟对码信号才有效
|
||||
if (AppManager_GetActiveAppID() == APP_ID_PAIR) {
|
||||
debug_evt.key_event = KEY_EVENT_NONE;
|
||||
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
debug_evt.extra_data = 0x789ABC; // 设定模拟对码硬件地址
|
||||
debug_evt.extra_size = 4;
|
||||
EventQueue_Push(debug_evt);
|
||||
Uart_SendString("[UART] Mock RF Pair Signal\r\n");
|
||||
} else {
|
||||
Uart_SendString("[UART] Not in PAIR mode\r\n");
|
||||
}
|
||||
} else if (cmd == '1') {
|
||||
// 模拟切换至 正常撤防 (NORMAL) 状态并刷新时钟
|
||||
if (AppManager_GetActiveAppID() == APP_ID_CLOCK) {
|
||||
current_state = STATE_NORMAL;
|
||||
UI_ShowClockPage(current_state, current_hour, current_min);
|
||||
}
|
||||
XTELL_LOG("[UART] State: NORMAL\r\n");
|
||||
Uart_SendString("[UART] State: NORMAL\r\n");
|
||||
} else if (cmd == '2') {
|
||||
// 模拟切换至 已布防 (ARMED) 状态,普通门磁可触发警报
|
||||
if (AppManager_GetActiveAppID() == APP_ID_CLOCK) {
|
||||
current_state = STATE_ARMED;
|
||||
UI_ShowClockPage(current_state, current_hour, current_min);
|
||||
}
|
||||
XTELL_LOG("[UART] State: ARMED\r\n");
|
||||
Uart_SendString("[UART] State: ARMED\r\n");
|
||||
} else if (cmd == '3') {
|
||||
// 模拟切换至 已撤防 (DISARMED) 状态,忽略普通报警
|
||||
if (AppManager_GetActiveAppID() == APP_ID_CLOCK) {
|
||||
current_state = STATE_DISARMED;
|
||||
UI_ShowClockPage(current_state, current_hour, current_min);
|
||||
}
|
||||
XTELL_LOG("[UART] State: DISARMED\r\n");
|
||||
Uart_SendString("[UART] State: DISARMED\r\n");
|
||||
} else if (cmd == 'z' || cmd == 'Z') {
|
||||
inactivity_timer = 6000; // 模拟闲置 60 秒超时,强制触发主循环深度休眠
|
||||
XTELL_LOG("[UART] Force Entering Sleep mode!\r\n");
|
||||
Uart_SendString("[UART] Force Entering Sleep mode!\r\n");
|
||||
} else if (cmd == 't' || cmd == 'T') {
|
||||
Loopback_Test(); // 调用回环测试验证屏幕
|
||||
RF_Test_Pin(); // 无线射频测试
|
||||
RF_DiagnosticMode('t'); // 触发射频连续发射诊断 (绿色爆闪)
|
||||
} else if (cmd == 'r' || cmd == 'R') {
|
||||
RF_DiagnosticMode('r'); // 触发 5 秒射频接收监听诊断
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,28 +170,25 @@ void main(void)
|
||||
GPIO_Init(); // 配置各个引脚的推挽输出/准双向模式及内部上拉
|
||||
RF_Init(); // 初始化射频芯片各引脚控制
|
||||
Delay_ms(500); // 软启动延时,等待供电电容稳定
|
||||
SGM_SendPulse(27); // 通过脉冲给 SGM3833 供电芯片发指令,稳压开启 LCD 正负电压轨
|
||||
Delay_ms(50); // 等待电压充盈稳定,避开浪涌
|
||||
LCD_Init(); // 初始化 Truly AMOLED 屏幕控制寄存器序列
|
||||
LCD_Init(); // 初始化 LHS114TC-IF03 (ST7789V) 屏幕控制寄存器序列并开启背光
|
||||
Uart1_Init(); // 初始化串口 1 波特率 115200 供调试日志
|
||||
XTELL_LOG("Wristband System Initialized!\r\n");
|
||||
Uart_SendString("Wristband System Initialized!\r\n");
|
||||
|
||||
Load_Database(); // 从 IAP Flash 第 254 扇区读取所有已绑定的传感器数据至 RAM
|
||||
|
||||
/* 步骤 1: 初始化事件环形缓冲区队列 */
|
||||
EventQueue_Init();
|
||||
|
||||
/* 步骤 2: 初始化应用管理器 */
|
||||
/* 步骤 2+5: 初始化应用管理器并登记所有前台应用,默认加载 ClockApp */
|
||||
AppManager_Init();
|
||||
|
||||
/* 步骤 3: 动态挂载待机时钟应用到前台,并挂载后台射频监控应用 */
|
||||
AppManager_SwitchToForeground(&clock_app);
|
||||
AppManager_AttachToBackground(&rf_monitor_app);
|
||||
|
||||
/* 启动 1ms 系统基准定时器 Timer1 */
|
||||
Timer1_Init();
|
||||
|
||||
XTELL_LOG("[SYS] Event-driven framework ready\r\n");
|
||||
/* 开机自动加载并运行待机时钟前台活跃应用 */
|
||||
AppManager_StartApp(APP_ID_CLOCK);
|
||||
|
||||
Uart_SendString("[SYS] Event-driven framework ready\r\n");
|
||||
|
||||
// ====== 主循环 ======
|
||||
while (1) {
|
||||
@@ -184,23 +203,23 @@ void main(void)
|
||||
Event_Dispatcher_Loop();
|
||||
}
|
||||
|
||||
/* 3. 应用调度中心:运行前后台所有已挂载激活的应用 */
|
||||
/* 3. 应用调度中心:运行当前处于前台活跃状态的应用(集成了 CPU 运行时间超时挂起保护) */
|
||||
AppManager_RunActiveApp();
|
||||
|
||||
/* 4. 自动休眠判定:常态无操作闲置达到 60 秒 (6000 * 10ms = 60s) 时,切入低功耗停机休眠 */
|
||||
if (inactivity_timer >= 6000) {
|
||||
inactivity_timer = 0;
|
||||
current_state = STATE_SLEEP; // 系统置为休眠状态
|
||||
Enter_Low_Power_Sleep(); // 挂起 MCU
|
||||
Enter_Low_Power_Sleep(); // 该函数是阻塞的,MCU 将在此挂起。唤醒后将自动从其后继续执行
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 唤醒源事件标志,由对应的外部中断 ISR 写入
|
||||
volatile u8 p0_wakeup_flag = 0; // P0 端口按键唤醒标志
|
||||
volatile u8 p2_wakeup_flag = 0; // P2 端口按键唤醒标志
|
||||
volatile u8 rf_wakeup_flag = 0; // P2.1 射频中断唤醒标志
|
||||
volatile u8 p3_wakeup_flag = 0; // P3 端口射频中断唤醒标志
|
||||
volatile u8 rf_wakeup_flag = 0; // 射频中断唤醒标志
|
||||
|
||||
/* =========================================================================
|
||||
* STC32G 端口掉电外部中断唤醒中断服务程序 (ISR)
|
||||
@@ -229,3 +248,15 @@ void Port2_Isr(void) interrupt 15
|
||||
P2INTF = 0x00; // 清除 P2 端口中断悬挂标志位
|
||||
P2INTE = 0x00; // 立即关闭 P2 中断通道,防止低电平期间反复重入
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Port3 端口掉电中断服务函数 (由 isr_jump.asm 引导定位至此)
|
||||
* @details 负责处理 P3.6 (新射频数据脚) 在休眠模式下的物理跳变唤醒。
|
||||
*/
|
||||
void Port3_Isr(void) interrupt 16
|
||||
{
|
||||
EAXFR = 1; // 使能访问扩展寄存区
|
||||
p3_wakeup_flag = P3INTF | 0x01;// 读取并备份 P3 中断标志寄存器值 (0x01作安全掩码)
|
||||
P3INTF = 0x00; // 清除 P3 端口中断悬挂标志位
|
||||
P3INTE = 0x00; // 立即关闭 P3 中断通道,防止反复重入
|
||||
}
|
||||
|
||||
BIN
App/system.c
BIN
App/system.c
Binary file not shown.
139
App/ui.c
139
App/ui.c
@@ -38,8 +38,8 @@ void UI_ShowClockPage(SystemState state, u8 hour, u8 min)
|
||||
}
|
||||
|
||||
// ====== 绘制右上角电池电量 ======
|
||||
LCD_ShowString(62, 24, "85%", COLOR_GRAY, COLOR_BLACK); // 静态测试显示 85% 字符
|
||||
LCD_DrawMonoBitmap(92, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK); // 渲染 20x10 电池外廓和格数
|
||||
LCD_ShowString(77, 24, "85%", COLOR_GRAY, COLOR_BLACK); // 静态测试显示 85% 字符并移动至右上角
|
||||
LCD_DrawMonoBitmap(107, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK); // 渲染 20x10 电池并移动至右上角
|
||||
|
||||
// ====== 绘制中部时间 "HH:MM" ======
|
||||
time_str[0] = '0' + (hour / 10); // 小时十位
|
||||
@@ -77,7 +77,7 @@ void UI_ShowPairMenuPage(u8 selected_index)
|
||||
}
|
||||
|
||||
// 渲染当前选中的高亮中间项
|
||||
LCD_DrawRectBorder(8, 110, 104, 28, COLOR_CYAN); // 青色对齐外框
|
||||
LCD_DrawRectBorder(15, 110, 104, 28, COLOR_CYAN); // 青色对齐外框 (在 135px 宽度下居中)
|
||||
LCD_ShowStringCentered(118, menu_items[selected_index], COLOR_CYAN, COLOR_BLACK);
|
||||
|
||||
// 渲染下方相邻项 (如果当前选择的不是最后一行)
|
||||
@@ -98,13 +98,13 @@ void UI_ShowPairWaitPage(u8 frame_index)
|
||||
// 绘制头部 "APPAIRAGE" (对码中)
|
||||
LCD_ShowStringCentered(35, "APPAIRAGE", COLOR_GRAY, COLOR_BLACK);
|
||||
|
||||
// 根据 Timer1 节拍算得的帧号,切换渲染雷达的 3 种点阵图形,形成扩散动态视觉
|
||||
// 根据 Timer1 节拍算得的帧号,切换渲染雷达的 3 种点阵图形,形成扩散动态视觉 (在 135px 下居中 X = 51)
|
||||
if (frame_index == 0)
|
||||
LCD_DrawMonoBitmap(44, 75, 32, 32, bmp_radar_32x32_f1, COLOR_CYAN, COLOR_BLACK);
|
||||
LCD_DrawMonoBitmap(51, 75, 32, 32, bmp_radar_32x32_f1, COLOR_CYAN, COLOR_BLACK);
|
||||
else if (frame_index == 1)
|
||||
LCD_DrawMonoBitmap(44, 75, 32, 32, bmp_radar_32x32_f2, COLOR_CYAN, COLOR_BLACK);
|
||||
LCD_DrawMonoBitmap(51, 75, 32, 32, bmp_radar_32x32_f2, COLOR_CYAN, COLOR_BLACK);
|
||||
else
|
||||
LCD_DrawMonoBitmap(44, 75, 32, 32, bmp_radar_32x32_f3, COLOR_CYAN, COLOR_BLACK);
|
||||
LCD_DrawMonoBitmap(51, 75, 32, 32, bmp_radar_32x32_f3, COLOR_CYAN, COLOR_BLACK);
|
||||
|
||||
// 绘制状态描述
|
||||
LCD_ShowStringCentered(165, "RECHERCHE", COLOR_WHITE, COLOR_BLACK); // 法语: 搜寻中
|
||||
@@ -124,24 +124,24 @@ void UI_ShowPairConfirmPage(u8 type, u8 zone_index)
|
||||
// 顶部显示捕获回馈标志 "v RECU" (法语: 信号已接收)
|
||||
LCD_ShowStringCentered(32, "v RECU", COLOR_GREEN, COLOR_BLACK);
|
||||
|
||||
// 在上部居中绘制设备类别所对应的图形
|
||||
// 在上部居中绘制设备类别所对应的图形 (135px 下居中 X = 51)
|
||||
if (type == 0) {
|
||||
LCD_DrawMonoBitmap(44, 55, 32, 32, bmp_door_32x32, COLOR_WHITE, COLOR_BLACK); // 门磁图标
|
||||
LCD_DrawMonoBitmap(51, 55, 32, 32, bmp_door_32x32, COLOR_WHITE, COLOR_BLACK); // 门磁图标
|
||||
} else if (type == 2 || type == 3) {
|
||||
LCD_DrawMonoBitmap(44, 55, 32, 32, bmp_siren_32x32, COLOR_WHITE, COLOR_BLACK); // 警号喇叭图标
|
||||
LCD_DrawMonoBitmap(51, 55, 32, 32, bmp_siren_32x32, COLOR_WHITE, COLOR_BLACK); // 警号喇叭图标
|
||||
} else {
|
||||
LCD_DrawMonoBitmap(44, 55, 32, 32, bmp_confirm_lock_32x32, COLOR_WHITE, COLOR_BLACK); // 锁型常规图标
|
||||
LCD_DrawMonoBitmap(51, 55, 32, 32, bmp_confirm_lock_32x32, COLOR_WHITE, COLOR_BLACK); // 锁型常规图标
|
||||
}
|
||||
|
||||
// 渲染传感器类型的文字
|
||||
LCD_ShowStringCentered(105, sensor_names_fr[type], COLOR_WHITE, COLOR_BLACK);
|
||||
|
||||
// 绘制一个青色边框,在中间以 16x32 大号字体展示当前防区号 (如 "01", "12")
|
||||
LCD_DrawRectBorder(15, 140, 90, 44, COLOR_CYAN);
|
||||
// 绘制一个青色边框,在中间以 16x32 大号字体展示当前防区号 (在 135px 下居中 X=22, 宽度 90)
|
||||
LCD_DrawRectBorder(22, 140, 90, 44, COLOR_CYAN);
|
||||
zone_str[0] = '0' + (zone_index / 10);
|
||||
zone_str[1] = '0' + (zone_index % 10);
|
||||
zone_str[2] = '\0';
|
||||
LCD_ShowString16x32(44, 146, zone_str, COLOR_CYAN, COLOR_BLACK); // 渲染两位防区编号
|
||||
LCD_ShowString16x32(51, 146, zone_str, COLOR_CYAN, COLOR_BLACK); // 渲染两位防区编号 (135px 下居中 X = 51)
|
||||
|
||||
// 底部提示按键动作
|
||||
LCD_ShowStringCentered(215, "CONFIRMER", COLOR_GRAY, COLOR_BLACK); // 法语: 短按以确认保存
|
||||
@@ -153,8 +153,8 @@ void UI_ShowPairConfirmPage(u8 type, u8 zone_index)
|
||||
void UI_ShowPairSuccessPage(void)
|
||||
{
|
||||
LCD_Clear(COLOR_BLACK);
|
||||
// 渲染 32x32 对勾图标
|
||||
LCD_DrawMonoBitmap(44, 75, 32, 32, bmp_checkmark_32x32, COLOR_GREEN, COLOR_BLACK);
|
||||
// 渲染 32x32 对勾图标 (135px 下居中 X = 51)
|
||||
LCD_DrawMonoBitmap(51, 75, 32, 32, bmp_checkmark_32x32, COLOR_GREEN, COLOR_BLACK);
|
||||
LCD_ShowStringCentered(145, "SUCCES", COLOR_GREEN, COLOR_BLACK); // 法语: 成功
|
||||
LCD_ShowStringCentered(180, "ENREGISTRE", COLOR_GRAY, COLOR_BLACK); // 法语: 配置已保存
|
||||
}
|
||||
@@ -166,8 +166,8 @@ void UI_ShowPairSuccessPage(void)
|
||||
void UI_ShowPairFailPage(u8 is_timeout)
|
||||
{
|
||||
LCD_Clear(COLOR_BLACK);
|
||||
// 渲染 32x32 红色叉号图标
|
||||
LCD_DrawMonoBitmap(44, 75, 32, 32, bmp_cross_32x32, COLOR_RED, COLOR_BLACK);
|
||||
// 渲染 32x32 红色叉号图标 (135px 下居中 X = 51)
|
||||
LCD_DrawMonoBitmap(51, 75, 32, 32, bmp_cross_32x32, COLOR_RED, COLOR_BLACK);
|
||||
LCD_ShowStringCentered(145, "ECHEC", COLOR_RED, COLOR_BLACK); // 法语: 失败
|
||||
if (is_timeout) {
|
||||
LCD_ShowStringCentered(180, "DELAI DEPASSE", COLOR_GRAY, COLOR_BLACK); // 法语: 对码超时
|
||||
@@ -189,17 +189,17 @@ void UI_ShowAlarmPage(u8 type, u8 zone_index)
|
||||
char zone_info[20];
|
||||
LCD_Clear(COLOR_BLACK);
|
||||
|
||||
// 绘制双重红色爆闪粗边界框 (配合 ms_tick 在 AlarmApp 中亮灭闪烁)
|
||||
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED);
|
||||
LCD_DrawRectBorder(6, 6, 108, 228, COLOR_RED);
|
||||
// 绘制双重红色爆闪粗边界框 (在新宽 135px 下对称扩展)
|
||||
LCD_DrawRectBorder(4, 4, 127, 232, COLOR_RED);
|
||||
LCD_DrawRectBorder(6, 6, 123, 228, COLOR_RED);
|
||||
|
||||
// 绘制报警设备的图形
|
||||
// 绘制报警设备的图形 (135px 下居中 X = 51)
|
||||
if (type == 0) {
|
||||
LCD_DrawMonoBitmap(44, 50, 32, 32, bmp_door_32x32, COLOR_RED, COLOR_BLACK); // 门磁报警
|
||||
LCD_DrawMonoBitmap(51, 50, 32, 32, bmp_door_32x32, COLOR_RED, COLOR_BLACK); // 门磁报警
|
||||
} else if (type == 2 || type == 3) {
|
||||
LCD_DrawMonoBitmap(44, 50, 32, 32, bmp_siren_32x32, COLOR_RED, COLOR_BLACK); // 烟感/燃气报警
|
||||
LCD_DrawMonoBitmap(51, 50, 32, 32, bmp_siren_32x32, COLOR_RED, COLOR_BLACK); // 烟感/燃气报警
|
||||
} else {
|
||||
LCD_DrawMonoBitmap(44, 50, 32, 32, bmp_confirm_lock_32x32, COLOR_RED, COLOR_BLACK); // 其他防区报警
|
||||
LCD_DrawMonoBitmap(51, 50, 32, 32, bmp_confirm_lock_32x32, COLOR_RED, COLOR_BLACK); // 其他防区报警
|
||||
}
|
||||
|
||||
// 拼接字符串: "设备类型名 两位防区号"
|
||||
@@ -227,19 +227,19 @@ void UI_ShowSosPage(void)
|
||||
{
|
||||
LCD_Clear(COLOR_BLACK);
|
||||
|
||||
// 绘制红白双层紧急警示框
|
||||
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED);
|
||||
LCD_DrawRectBorder(5, 5, 110, 230, COLOR_RED);
|
||||
LCD_DrawRectBorder(8, 8, 104, 224, COLOR_WHITE);
|
||||
// 绘制红白双层紧急警示框 (在新宽 135px 下对称扩展)
|
||||
LCD_DrawRectBorder(4, 4, 127, 232, COLOR_RED);
|
||||
LCD_DrawRectBorder(5, 5, 125, 230, COLOR_RED);
|
||||
LCD_DrawRectBorder(8, 8, 119, 224, COLOR_WHITE);
|
||||
|
||||
// ====== 用画点和填充矩形函数像素级绘制精细的警徽灯架 ======
|
||||
LCD_FillRect(44, 45, 32, 2, COLOR_RED); // 警灯顶部
|
||||
LCD_FillRect(48, 47, 24, 12, COLOR_RED); // 警灯红色灯罩
|
||||
LCD_FillRect(40, 59, 40, 4, COLOR_GRAY); // 警灯灰色底座
|
||||
LCD_FillRect(57, 51, 6, 6, COLOR_WHITE); // 中间高亮光影
|
||||
LCD_FillRect(58, 36, 4, 6, COLOR_RED); // 发射的垂直红色闪光
|
||||
LCD_FillRect(46, 38, 4, 4, COLOR_RED); // 左侧散射闪光
|
||||
LCD_FillRect(70, 38, 4, 4, COLOR_RED); // 右侧散射闪光
|
||||
// ====== 用画点和填充矩形函数像素级绘制精细的警徽灯架 (在新宽 135px 下整体右移 7 像素) ======
|
||||
LCD_FillRect(51, 45, 32, 2, COLOR_RED); // 警灯顶部
|
||||
LCD_FillRect(55, 47, 24, 12, COLOR_RED); // 警灯红色灯罩
|
||||
LCD_FillRect(47, 59, 40, 4, COLOR_GRAY); // 警灯灰色底座
|
||||
LCD_FillRect(64, 51, 6, 6, COLOR_WHITE); // 中间高亮光影
|
||||
LCD_FillRect(65, 36, 4, 6, COLOR_RED); // 发射的垂直红色闪光
|
||||
LCD_FillRect(53, 38, 4, 4, COLOR_RED); // 左侧散射闪光
|
||||
LCD_FillRect(77, 38, 4, 4, COLOR_RED); // 右侧散射闪光
|
||||
|
||||
// 绘制求救中法文字样
|
||||
LCD_ShowStringCentered(120, "SOS", COLOR_RED, COLOR_BLACK);
|
||||
@@ -257,11 +257,11 @@ void UI_ShowBindingPage(u32 addr)
|
||||
LCD_Clear(COLOR_BLACK);
|
||||
|
||||
// ====== 像素级拼装绘制一个青色网络摄像头简图 ======
|
||||
LCD_DrawRectBorder(36, 46, 32, 26, COLOR_CYAN); // 相机主体框
|
||||
LCD_FillRect(44, 56, 6, 6, COLOR_CYAN); // 镜头光圈点
|
||||
LCD_FillRect(68, 48, 2, 22, COLOR_CYAN); // 右侧红外指示圈
|
||||
LCD_FillRect(70, 50, 2, 18, COLOR_CYAN); // 镜头固定翼 1
|
||||
LCD_FillRect(72, 52, 2, 14, COLOR_CYAN); // 镜头固定翼 2
|
||||
LCD_DrawRectBorder(43, 46, 32, 26, COLOR_CYAN); // 相机主体框 (135px 下居中等比右移 X = 43)
|
||||
LCD_FillRect(51, 56, 6, 6, COLOR_CYAN); // 镜头光圈点 (135px 下居中等比右移 X = 51)
|
||||
LCD_FillRect(75, 48, 2, 22, COLOR_CYAN); // 右侧红外指示圈 (135px 下居中等比右移 X = 75)
|
||||
LCD_FillRect(77, 50, 2, 18, COLOR_CYAN); // 镜头固定翼 1 (135px 下居中等比右移 X = 77)
|
||||
LCD_FillRect(79, 52, 2, 14, COLOR_CYAN); // 镜头固定翼 2 (135px 下居中等比右移 X = 79)
|
||||
|
||||
LCD_ShowStringCentered(120, "LIAISON", COLOR_WHITE, COLOR_BLACK); // 法语: 连接/绑定
|
||||
LCD_ShowStringCentered(155, "ENVOI EN COURS", COLOR_CYAN, COLOR_BLACK); // 法语: 发送对码帧中
|
||||
@@ -294,46 +294,46 @@ void UI_ShowBindingPage(u32 addr)
|
||||
* @brief 渲染显示设置主菜单界面
|
||||
* @param selected_index 当前菜单高亮行索引 (0:时钟修改, 1:对码匹配, 2:摄像机绑定)
|
||||
* @details 在顶部和底部绘制向上/向下箭头提示滑轮,中部绘制选中项的大几何图形,
|
||||
* 并在下方打印对应的法文字符串描述。
|
||||
* 并在下方打印对应的法文字串描述。
|
||||
*/
|
||||
void UI_ShowMainMenu(u8 selected_index)
|
||||
{
|
||||
LCD_Clear(COLOR_BLACK);
|
||||
|
||||
// ====== 绘制顶部的向上箭头三角标记 ======
|
||||
LCD_FillRect(58, 20, 4, 2, COLOR_GRAY);
|
||||
LCD_FillRect(56, 22, 8, 2, COLOR_GRAY);
|
||||
LCD_FillRect(54, 24, 12, 2, COLOR_GRAY);
|
||||
// ====== 绘制顶部的向上箭头三角标记 (在 135px 宽度下居中) ======
|
||||
LCD_FillRect(65, 20, 4, 2, COLOR_GRAY);
|
||||
LCD_FillRect(63, 22, 8, 2, COLOR_GRAY);
|
||||
LCD_FillRect(61, 24, 12, 2, COLOR_GRAY);
|
||||
|
||||
if (selected_index == 0)
|
||||
{
|
||||
// 菜单 0:时间修改设置。中部绘制一个青色闹钟样式
|
||||
LCD_DrawRectBorder(44, 70, 32, 32, COLOR_CYAN); // 闹钟外圈
|
||||
LCD_FillRect(59, 76, 2, 10, COLOR_CYAN); // 闹钟时针
|
||||
LCD_FillRect(59, 85, 8, 2, COLOR_CYAN); // 闹钟分针
|
||||
// 菜单 0:时间修改设置。中部绘制一个青色闹钟样式 (135px 下居中 X = 51)
|
||||
LCD_DrawRectBorder(51, 70, 32, 32, COLOR_CYAN); // 闹钟外圈
|
||||
LCD_FillRect(66, 76, 2, 10, COLOR_CYAN); // 闹钟时针
|
||||
LCD_FillRect(66, 85, 8, 2, COLOR_CYAN); // 闹钟分针
|
||||
LCD_ShowStringCentered(150, "1. HORLOGE", COLOR_WHITE, COLOR_BLACK); // 法语: 时钟/时间修改
|
||||
}
|
||||
else if (selected_index == 1)
|
||||
{
|
||||
// 菜单 1:无线对码匹配。中部绘制一个青色同心圆雷达波纹图形
|
||||
LCD_DrawMonoBitmap(44, 70, 32, 32, bmp_radar_32x32_f3, COLOR_CYAN, COLOR_BLACK);
|
||||
// 菜单 1:无线对码匹配。中部绘制一个青色同心圆雷达波纹图形 (135px 下居中 X = 51)
|
||||
LCD_DrawMonoBitmap(51, 70, 32, 32, bmp_radar_32x32_f3, COLOR_CYAN, COLOR_BLACK);
|
||||
LCD_ShowStringCentered(150, "2. APPAIRAGE", COLOR_WHITE, COLOR_BLACK); // 法语: 配对
|
||||
}
|
||||
else if (selected_index == 2)
|
||||
{
|
||||
// 菜单 2:网络摄像机绑定。中部绘制一个相机/联通关系图
|
||||
LCD_DrawRectBorder(44, 74, 20, 16, COLOR_CYAN);
|
||||
LCD_FillRect(52, 80, 4, 4, COLOR_CYAN);
|
||||
LCD_FillRect(64, 76, 2, 12, COLOR_CYAN);
|
||||
LCD_FillRect(66, 78, 2, 8, COLOR_CYAN);
|
||||
LCD_FillRect(68, 80, 2, 4, COLOR_CYAN);
|
||||
// 菜单 2:网络摄像机绑定。中部绘制一个相机/联通关系图 (135px 下居中等比右移 X = 57)
|
||||
LCD_DrawRectBorder(57, 74, 20, 16, COLOR_CYAN);
|
||||
LCD_FillRect(65, 80, 4, 4, COLOR_CYAN);
|
||||
LCD_FillRect(77, 76, 2, 12, COLOR_CYAN);
|
||||
LCD_FillRect(79, 78, 2, 8, COLOR_CYAN);
|
||||
LCD_FillRect(81, 80, 2, 4, COLOR_CYAN);
|
||||
LCD_ShowStringCentered(150, "3. LIAISON", COLOR_WHITE, COLOR_BLACK); // 法语: 摄像机绑定
|
||||
}
|
||||
|
||||
// ====== 绘制底部的向下箭头三角标记 ======
|
||||
LCD_FillRect(54, 210, 12, 2, COLOR_GRAY);
|
||||
LCD_FillRect(56, 212, 8, 2, COLOR_GRAY);
|
||||
LCD_FillRect(58, 214, 4, 2, COLOR_GRAY);
|
||||
// ====== 绘制底部的向下箭头三角标记 (在 135px 宽度下居中) ======
|
||||
LCD_FillRect(61, 210, 12, 2, COLOR_GRAY);
|
||||
LCD_FillRect(63, 212, 8, 2, COLOR_GRAY);
|
||||
LCD_FillRect(65, 214, 4, 2, COLOR_GRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,8 +354,9 @@ void UI_ShowSetTimePage(u8 hour, u8 min, u8 selection, u8 blink_on)
|
||||
LCD_FillRect(17, 15, 8, 2, COLOR_GREEN);
|
||||
LCD_FillRect(25, 17, 2, 6, COLOR_GREEN);
|
||||
|
||||
LCD_ShowString(62, 24, "85%", COLOR_GRAY, COLOR_BLACK);
|
||||
LCD_DrawMonoBitmap(92, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK);
|
||||
// 移动电池百分比和图标到 135px 右上角
|
||||
LCD_ShowString(77, 24, "85%", COLOR_GRAY, COLOR_BLACK);
|
||||
LCD_DrawMonoBitmap(107, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK);
|
||||
|
||||
// ====== 处理调节项一:小时的消隐/显示逻辑 ======
|
||||
if (selection == 1 && !blink_on)
|
||||
@@ -370,10 +371,10 @@ void UI_ShowSetTimePage(u8 hour, u8 min, u8 selection, u8 blink_on)
|
||||
time_str[1] = '0' + (hour % 10);
|
||||
}
|
||||
time_str[2] = '\0';
|
||||
LCD_ShowString16x32(12, 100, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘小时
|
||||
LCD_ShowString16x32(23, 100, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘小时 (在 135px 下整体居中 X = 23)
|
||||
|
||||
// 绘制中间冒号
|
||||
LCD_ShowString16x32(48, 98, ":", COLOR_WHITE, COLOR_BLACK);
|
||||
// 绘制中间冒号 (在 135px 下整体居中 X = 59)
|
||||
LCD_ShowString16x32(59, 98, ":", COLOR_WHITE, COLOR_BLACK);
|
||||
|
||||
// ====== 处理调节项二:分钟的消隐/显示逻辑 ======
|
||||
if (selection == 2 && !blink_on)
|
||||
@@ -388,7 +389,7 @@ void UI_ShowSetTimePage(u8 hour, u8 min, u8 selection, u8 blink_on)
|
||||
time_str[1] = '0' + (min % 10);
|
||||
}
|
||||
time_str[2] = '\0';
|
||||
LCD_ShowString16x32(64, 100, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘分钟
|
||||
LCD_ShowString16x32(75, 100, time_str, COLOR_CYAN, COLOR_BLACK); // 采用青色特大字描绘分钟 (在 135px 下整体居中 X = 75)
|
||||
|
||||
// 补齐底部的固定辅助元素
|
||||
LCD_ShowStringCentered(150, "AM", COLOR_WHITE, COLOR_BLACK);
|
||||
|
||||
Reference in New Issue
Block a user