docs: 为所有代码源文件添加详细中文注释,并在设计文档中纠正GPIO物理引脚映射表
This commit is contained in:
203
App/event.c
203
App/event.c
@@ -3,13 +3,18 @@
|
||||
#include "database.h"
|
||||
#include "system.h"
|
||||
|
||||
// 定义事件环形队列的最大深度为 8
|
||||
#define EVENT_QUEUE_DEPTH 8
|
||||
|
||||
// 环形队列存储数组 (存放在单片机 idata 快速RAM区中)
|
||||
static SystemEvent idata event_queue[EVENT_QUEUE_DEPTH];
|
||||
static u8 queue_head = 0;
|
||||
static u8 queue_tail = 0;
|
||||
static u8 queue_count = 0;
|
||||
static u8 queue_head = 0; // 队首读指针
|
||||
static u8 queue_tail = 0; // 队尾写指针
|
||||
static u8 queue_count = 0; // 当前队列内有效事件总数
|
||||
|
||||
/**
|
||||
* @brief 初始化/清空事件队列
|
||||
*/
|
||||
void EventQueue_Init(void)
|
||||
{
|
||||
queue_head = 0;
|
||||
@@ -17,163 +22,217 @@ void EventQueue_Init(void)
|
||||
queue_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将普通事件压入队尾
|
||||
* @param evt 输入的系统事件
|
||||
* @return bit 1-成功,0-失败
|
||||
*/
|
||||
bit EventQueue_Push(SystemEvent evt)
|
||||
{
|
||||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0;
|
||||
EA = 0;
|
||||
event_queue[queue_tail] = evt;
|
||||
queue_tail = (queue_tail + 1) % EVENT_QUEUE_DEPTH;
|
||||
queue_count++;
|
||||
EA = 1;
|
||||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,丢弃事件
|
||||
EA = 0; // 关闭全局中断,保护临界区操作的原子性
|
||||
event_queue[queue_tail] = evt; // 存入队尾
|
||||
queue_tail = (queue_tail + 1) % EVENT_QUEUE_DEPTH; // 尾指针向后移动,回环
|
||||
queue_count++; // 有效计数加 1
|
||||
EA = 1; // 恢复全局中断
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将高优先级/紧急事件强行插到队首
|
||||
* @param evt 输入的系统事件
|
||||
* @return bit 1-成功,0-失败
|
||||
*/
|
||||
bit EventQueue_InsertFront(SystemEvent evt)
|
||||
{
|
||||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0;
|
||||
EA = 0;
|
||||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,插队失败
|
||||
EA = 0; // 屏蔽中断
|
||||
// 头指针向前移动一位(带回环防溢出)
|
||||
queue_head = (queue_head - 1 + EVENT_QUEUE_DEPTH) % EVENT_QUEUE_DEPTH;
|
||||
event_queue[queue_head] = evt;
|
||||
queue_count++;
|
||||
EA = 1;
|
||||
event_queue[queue_head] = evt; // 存入腾出的队首位置
|
||||
queue_count++; // 计数加 1
|
||||
EA = 1; // 恢复中断
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从队首弹出一个缓冲事件
|
||||
* @return SystemEvent 返回弹出的事件。若空返回空闲事件
|
||||
*/
|
||||
SystemEvent EventQueue_Pop(void)
|
||||
{
|
||||
SystemEvent evt;
|
||||
// 默认空事件属性
|
||||
evt.key_event = KEY_EVENT_NONE;
|
||||
evt.priority = EVENT_PRIORITY_LOW;
|
||||
evt.extra_data = 0;
|
||||
evt.extra_size = 0;
|
||||
if (queue_count == 0) return evt;
|
||||
EA = 0;
|
||||
evt = event_queue[queue_head];
|
||||
queue_head = (queue_head + 1) % EVENT_QUEUE_DEPTH;
|
||||
queue_count--;
|
||||
EA = 1;
|
||||
|
||||
if (queue_count == 0) return evt; // 队空,直接返回空闲事件
|
||||
|
||||
EA = 0; // 屏蔽中断
|
||||
evt = event_queue[queue_head]; // 读取队首数据
|
||||
queue_head = (queue_head + 1) % EVENT_QUEUE_DEPTH; // 头指针向后移动,回环
|
||||
queue_count--; // 有效计数减 1
|
||||
EA = 1; // 恢复中断
|
||||
return evt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断队列是否为空
|
||||
*/
|
||||
bit EventQueue_IsEmpty(void)
|
||||
{
|
||||
return (queue_count == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断队列是否已满
|
||||
*/
|
||||
bit EventQueue_IsFull(void)
|
||||
{
|
||||
return (queue_count >= EVENT_QUEUE_DEPTH) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前队列中的事件总数
|
||||
*/
|
||||
u8 EventQueue_GetCount(void)
|
||||
{
|
||||
return queue_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 事件分发器核心轮询逻辑
|
||||
* @details 逐一处理队列中的事件,并根据系统当前的运行模式进行拦截、跳转或下发派发。
|
||||
*/
|
||||
void Event_Dispatcher_Loop(void)
|
||||
{
|
||||
SystemEvent evt = EventQueue_Pop();
|
||||
SystemEvent evt = EventQueue_Pop(); // 弹出一个事件
|
||||
|
||||
// 如果是无事发生的空事件,直接退出
|
||||
if (evt.key_event == KEY_EVENT_NONE && evt.extra_size == 0) {
|
||||
return;
|
||||
}
|
||||
inactivity_timer = 0; // 收到有效按键或无线事件,重置闲置计时器
|
||||
|
||||
inactivity_timer = 0; // 捕获到有效事件,清零休眠计时器,重置闲置超时
|
||||
|
||||
// 串口打印调试信息
|
||||
Uart_SendString("[EVENT] key=");
|
||||
Uart_SendHex8((u8)evt.key_event);
|
||||
Uart_SendString(", pri=");
|
||||
Uart_SendHex8((u8)evt.priority);
|
||||
Uart_SendString("\r\n");
|
||||
|
||||
// SOS 按键:仅在当前不处于 SOS 求求模式时触发进入 SOS 状态,否则作为普通按键进行事件分发
|
||||
// SOS 按键紧急处理:若非处于 SOS 呼救状态下,接收到 SOS 键动作,立即强行切入到 SOS_APP 并执行求救
|
||||
if ((evt.key_event == KEY_EVENT_SOS_CLICK || evt.key_event == KEY_EVENT_SOS_LONG) &&
|
||||
AppManager_GetActiveAppID() != APP_ID_SOS) {
|
||||
AppManager_StartApp(APP_ID_SOS);
|
||||
return;
|
||||
}
|
||||
|
||||
// 传感器入侵警报:当前不处于 SOS 求救状态时方可跳转到报警界面
|
||||
// 传感器入侵报警过滤与跳转处理:
|
||||
// 当接收到高优先级且带有 4 字节射频地址的数据包,说明有传感器触发了发射
|
||||
if (evt.priority == EVENT_PRIORITY_HIGH && evt.extra_size >= 4) {
|
||||
u8 slot;
|
||||
// 在本地数据库中检索该传感器地址是否合法登记过
|
||||
if (Check_Sensor_ID(evt.extra_data, &slot)) {
|
||||
// 在不处于 SOS 的情况下,可正常强行切入 ALARM_APP 触发声光振警报
|
||||
if (AppManager_GetActiveAppID() != APP_ID_SOS) {
|
||||
captured_addr = evt.extra_data;
|
||||
alarm_sensor_slot = slot;
|
||||
AppManager_StartApp(APP_ID_ALARM);
|
||||
captured_addr = evt.extra_data; // 缓存报警地址
|
||||
alarm_sensor_slot = slot; // 缓存报警槽位
|
||||
AppManager_StartApp(APP_ID_ALARM); // 强制切入报警前台
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 无线对码捕获:处于 PAIR 模式下时,将射频事件分发给 PairApp 处理并退出分发
|
||||
// 无线对码捕获处理:
|
||||
// 若系统正处于对码应用 (APP_ID_PAIR),遇到普通优先级无线射频包,则将其派发给该应用进行匹配与登记
|
||||
if (evt.priority == EVENT_PRIORITY_NORMAL && evt.extra_size >= 4) {
|
||||
captured_addr = evt.extra_data;
|
||||
captured_type = menu_select;
|
||||
captured_addr = evt.extra_data; // 缓存捕获的待配对地址
|
||||
captured_type = menu_select; // 将主菜单选择的类型传给配对缓存
|
||||
if (AppManager_GetActiveAppID() == APP_ID_PAIR) {
|
||||
AppManager_DispatchEvent(evt);
|
||||
AppManager_DispatchEvent(evt); // 派发给对码应用
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 常规事件(如普通的按键点击)直接透传分发给当前处于前台活跃的应用
|
||||
AppManager_DispatchEvent(evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 定时器 1 初始化,设定 1ms 中断周期
|
||||
*/
|
||||
void Timer1_Init(void)
|
||||
{
|
||||
AUXR |= 0x40;
|
||||
TMOD &= 0x0F;
|
||||
AUXR |= 0x40; // 设定定时器 1 为 1T 模式 (无分频,主频直接输入)
|
||||
TMOD &= 0x0F; // 设置定时器 1 模式寄存器,保留低四位 (定时器0配置)
|
||||
{
|
||||
// 按照系统主频 (MAIN_Fosc) 计算 1ms 对应的重装载值
|
||||
u16 reload = (u16)(65536UL - (MAIN_Fosc / 1000UL));
|
||||
TL1 = (u8)reload;
|
||||
TH1 = (u8)(reload >> 8);
|
||||
TL1 = (u8)reload; // 载入低 8 位
|
||||
TH1 = (u8)(reload >> 8);// 载入高 8 位
|
||||
}
|
||||
ET1 = 1;
|
||||
TR1 = 1;
|
||||
EA = 1;
|
||||
ET1 = 1; // 开启定时器 1 中断允许
|
||||
TR1 = 1; // 启动定时器 1 计数
|
||||
EA = 1; // 开启全局中断允许
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 定时器 1 中断服务程序 (每 1ms 触发一次)
|
||||
* @details 承担了系统软时钟计算、报警与求救下的马达控制状态机以及 10ms 周期性按键消抖扫描的功能。
|
||||
*/
|
||||
void Timer1_Isr(void) interrupt 3
|
||||
{
|
||||
SystemEvent evt;
|
||||
|
||||
// 1ms 递增滴答
|
||||
ms_tick++;
|
||||
if (ms_tick >= 1000) {
|
||||
ms_tick = 0;
|
||||
ms_tick = 0; // 1秒时间已到,归零
|
||||
current_sec++;
|
||||
if (current_sec >= 60) {
|
||||
current_sec = 0;
|
||||
current_sec = 0; // 1分钟时间已到
|
||||
current_min++;
|
||||
if (current_min >= 60) {
|
||||
current_min = 0;
|
||||
current_min = 0; // 1小时时间已到
|
||||
current_hour++;
|
||||
if (current_hour >= 24) current_hour = 0;
|
||||
if (current_hour >= 24) current_hour = 0; // 小时循环
|
||||
}
|
||||
clock_updated = 1;
|
||||
clock_updated = 1; // 标志位置1,提示前台时钟应用刷新显示
|
||||
}
|
||||
}
|
||||
|
||||
// 如果处于对码等待状态,对码超时计时器增加 (30秒超时判断)
|
||||
if (current_state == STATE_PAIR_WAIT) {
|
||||
pair_timeout_ms++;
|
||||
}
|
||||
|
||||
/* 振动马达定时状态机(仅控制马达,不再控制已被挪用/废弃的 LED) */
|
||||
/* 振动马达定时状态机逻辑控制 */
|
||||
if (current_state == STATE_SOS_EMITTED) {
|
||||
// SOS 模式:交替规律震动 (震动 1000ms,静音 200ms)
|
||||
alarm_timer_ms++;
|
||||
if (alarm_timer_ms >= 1200) alarm_timer_ms = 0;
|
||||
if (alarm_timer_ms < 1000) MOTOR = 1; else MOTOR = 0;
|
||||
} 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;
|
||||
if (alarm_timer_ms >= 5000) alarm_timer_ms = 0; // 5秒一周期
|
||||
|
||||
if (stype == 0) {
|
||||
// 门磁警报振动波形
|
||||
// 门磁警报波形:单次震动 300ms,停 4700ms
|
||||
if (alarm_timer_ms < 300) MOTOR = 1; else MOTOR = 0;
|
||||
} else if (stype == 1) {
|
||||
// PIR 警报振动波形
|
||||
// PIR 警报波形:震动 300ms,停 200ms,再震动 300ms,停 4200ms
|
||||
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) {
|
||||
// 烟感警报振动波形
|
||||
// 烟感警报波形:急促短闪三下 200ms-150ms-200ms-150ms-200ms
|
||||
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;
|
||||
@@ -181,7 +240,7 @@ void Timer1_Isr(void) interrupt 3
|
||||
else if (alarm_timer_ms >= 700 && alarm_timer_ms < 900) MOTOR = 1;
|
||||
else MOTOR = 0;
|
||||
} else if (stype == 3) {
|
||||
// 气感警报振动波形
|
||||
// 燃气报警波形:快频连续四下
|
||||
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;
|
||||
@@ -191,75 +250,85 @@ void Timer1_Isr(void) interrupt 3
|
||||
else if (alarm_timer_ms >= 900 && alarm_timer_ms < 1100) MOTOR = 1;
|
||||
else MOTOR = 0;
|
||||
} else if (stype == 4) {
|
||||
// 水浸警报振动波形
|
||||
// 水浸警报波形:慢速双长震波 600ms 和 600ms
|
||||
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 {
|
||||
// 缺省状态默认单次 300ms
|
||||
if (alarm_timer_ms < 300) MOTOR = 1; else MOTOR = 0;
|
||||
}
|
||||
} else {
|
||||
// 其他常态下彻底关闭震动马达并归零计时器
|
||||
MOTOR = 0;
|
||||
alarm_timer_ms = 0;
|
||||
motor_timer_ms = 0;
|
||||
}
|
||||
|
||||
// 报警屏幕红边框以 100ms 周期亮灭,进行颜色爆闪指示
|
||||
alarm_flash_flag = (ms_tick / 100) % 2;
|
||||
|
||||
/* 按键消抖扫描 (每10ms) */
|
||||
/* 物理按键扫描及消抖状态机逻辑 (每 10ms 轮询一次) */
|
||||
key_scan_timer++;
|
||||
if (key_scan_timer >= 10) {
|
||||
// 读取按键的电平信号 (由于有上拉电阻,未按下为高 1,按下为低 0,所以取反做正逻辑)
|
||||
u8 raw_up = !KEY_UP;
|
||||
u8 raw_down = !KEY_DOWN;
|
||||
u8 raw_confirm = !KEY_CONFIRM;
|
||||
u8 raw_sos = !KEY_SOS;
|
||||
key_scan_timer = 0;
|
||||
key_scan_timer = 0; // 重置扫描分频计数器
|
||||
|
||||
// 如果检测到有任何按键按下,清零闲置计时器;否则在非休眠非警报下累加
|
||||
// 检测到有任意按键处于下压状态,立即将无操作闲置休眠计时器归零
|
||||
if (raw_up || raw_down || raw_confirm || raw_sos) {
|
||||
inactivity_timer = 0;
|
||||
} else {
|
||||
// 如果在常态下(非休眠、非报警、非紧急求救),累加闲置时间
|
||||
if (current_state != STATE_SLEEP && current_state != STATE_ALARM && current_state != STATE_SOS_EMITTED) {
|
||||
inactivity_timer++;
|
||||
}
|
||||
}
|
||||
|
||||
// 默认将派发事件重置为空
|
||||
evt.key_event = KEY_EVENT_NONE;
|
||||
evt.extra_data = 0;
|
||||
evt.extra_size = 0;
|
||||
|
||||
// 双键组合判定:▲ 键和 ▼ 键同时按下的消抖与生成
|
||||
if (raw_up && raw_down) {
|
||||
comb_hold++;
|
||||
if (comb_hold == 300) {
|
||||
if (comb_hold == 300) { // 持续按下达 3 秒 (300 * 10ms = 3s)
|
||||
evt.key_event = KEY_EVENT_UP_DOWN_COMB;
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(evt);
|
||||
EventQueue_Push(evt); // 压入队列
|
||||
}
|
||||
key_up_hold = 0;
|
||||
key_up_hold = 0; // 清零单个按键计数,防止双击事件干扰
|
||||
key_down_hold = 0;
|
||||
} else {
|
||||
comb_hold = 0;
|
||||
comb_hold = 0; // 组合键松开归零
|
||||
|
||||
// ▲ (KEY_UP) 按键状态机
|
||||
if (raw_up) {
|
||||
key_up_hold++;
|
||||
if (key_up_hold == 300) {
|
||||
if (key_up_hold == 300) { // 达到 3 秒判定为长按
|
||||
evt.key_event = KEY_EVENT_UP_LONG;
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(evt);
|
||||
}
|
||||
} else {
|
||||
// 如果松开时按下计数在消抖阈值(20ms)至长按阈值(3s)之间,则判定为一次短按
|
||||
if (key_up_hold >= 2 && key_up_hold < 300) {
|
||||
evt.key_event = KEY_EVENT_UP_CLICK;
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(evt);
|
||||
}
|
||||
key_up_hold = 0;
|
||||
key_up_hold = 0; // 释放归零
|
||||
}
|
||||
|
||||
// ▼ (KEY_DOWN) 按键状态机
|
||||
if (raw_down) {
|
||||
key_down_hold++;
|
||||
if (key_down_hold == 300) {
|
||||
if (key_down_hold == 300) { // 长按 3 秒
|
||||
evt.key_event = KEY_EVENT_DOWN_LONG;
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(evt);
|
||||
@@ -270,12 +339,13 @@ void Timer1_Isr(void) interrupt 3
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(evt);
|
||||
}
|
||||
key_down_hold = 0;
|
||||
key_down_hold = 0; // 释放归零
|
||||
}
|
||||
|
||||
// ■ (KEY_CONFIRM) 确认按键状态机
|
||||
if (raw_confirm) {
|
||||
key_confirm_hold++;
|
||||
if (key_confirm_hold == 300) {
|
||||
if (key_confirm_hold == 300) { // 长按 3 秒打开主菜单
|
||||
evt.key_event = KEY_EVENT_CONFIRM_LONG;
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(evt);
|
||||
@@ -286,23 +356,24 @@ void Timer1_Isr(void) interrupt 3
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
EventQueue_Push(evt);
|
||||
}
|
||||
key_confirm_hold = 0;
|
||||
key_confirm_hold = 0; // 释放归零
|
||||
}
|
||||
|
||||
// SOS 物理求救按键状态机
|
||||
if (raw_sos) {
|
||||
key_sos_hold++;
|
||||
if (key_sos_hold == 300) {
|
||||
if (key_sos_hold == 300) { // 长按 3 秒,发出 URGENT 优先级求救,插入队首
|
||||
evt.key_event = KEY_EVENT_SOS_LONG;
|
||||
evt.priority = EVENT_PRIORITY_URGENT;
|
||||
EventQueue_InsertFront(evt);
|
||||
}
|
||||
} else {
|
||||
if (key_sos_hold >= 2 && key_sos_hold < 300) {
|
||||
if (key_sos_hold >= 2 && key_sos_hold < 300) { // 短按即呼救,插入队首
|
||||
evt.key_event = KEY_EVENT_SOS_CLICK;
|
||||
evt.priority = EVENT_PRIORITY_URGENT;
|
||||
EventQueue_InsertFront(evt);
|
||||
}
|
||||
key_sos_hold = 0;
|
||||
key_sos_hold = 0; // 释放归零
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user