接入温湿度风扇产品固件(仲裁/条件/定时/显示),并补齐规格书与外设驱动

新增 usr_app 产品逻辑:手动>定时>条件仲裁、条件控温湿、定时任务、数码管显示、
按键/LED、风扇档位、NVM 掉电恢复、配对与开关机,上电按规格恢复上次状态。
新增 usr_periph:AHT20、CT1642、板级引脚与硬件封装;见宝协议 cond_config
改为 7 字节编解码,并接入产品 DP。
补充《温湿度风扇_固件需求规格书》,工程加入对应源文件。
.gitignore 忽略 WorkBuddy/Cursor 本地会话
This commit is contained in:
2026-08-31 15:17:27 +08:00
parent 4cb7418a02
commit 5cc7e9dbd6
53 changed files with 7028 additions and 513 deletions
+220
View File
@@ -0,0 +1,220 @@
/******************************************************************************
* @file app_function.c
* @brief CBR3 功能总装实现
* @author cyWu <1917507415@qq.com>
* @date 2026.08.29
* @version V1.1.0
* @history
* - V1.0.0, 2026.08.29, cyWu, 首次发布
* - V1.1.0, 2026.08.31, cyWu, 长按关机改为延后到任务上下文执行:按键在
* usr_timer 20ms(硬件定时器中断上下文)里处理,直接调
* app_power_request_poweroff 会在中断里跑 VM 落盘(栈溢出复位);
* 现改为置 off_pending,由 app_function_loopusr_timer_loop
* BLE 线程)先落盘再关机
******************************************************************************/
#include "app_function.h"
#include "app_power.h"
#include "app_pair.h"
#include "app_mode.h"
#include "app_fan.h"
#include "app_nvm.h"
#include "app_arbiter.h"
#include "app_cond.h"
#include "app_timer_task.h"
#include "app_th.h"
#include "app_disp.h"
#include "app_led.h"
#include "jb_product.h"
#include "system/includes.h"
#include <string.h>
#define LOG_TAG_CONST APP
#define LOG_TAG "[APP_FUNC]"
#define LOG_INFO_ENABLE
#include "debug.h"
/** 功能模块状态 */
typedef struct {
uint8_t app_power; /**< DP01=开机态(本产品无 APP 软关) */
uint8_t off_pending; /**< 1=长按已触发关机,等任务上下文落盘后再关机 */
} AppFunctionCtx_t;
static AppFunctionCtx_t s_func;
/**
* @brief 初始化功能模块状态
* @return 无
*/
void app_function_init(void)
{
s_func.app_power = 0;
s_func.off_pending = 0;
}
/**
* @brief 任务上下文周期处理(由 usr_timer_loop 500ms 调用)
* @note ⚠ 本函数是唯一允许做 VM 落盘与关机收口的地方:usr_timer_loop 跑在
* BLE 线程(sys_timer 同步接口,任务上下文,栈充足)。20ms 的
* usr_timer_tick 是硬件定时器中断上下文,禁止做这两件事。
* @return 无
*/
void app_function_loop(void)
{
app_nvm_flush(); /* 防抖满后真正写 VMsyscfg_write 必须在任务上下文) */
if (s_func.off_pending) {
s_func.off_pending = 0;
app_power_request_poweroff(); /* 落盘后再走关机流程 */
}
}
/**
* @brief 同步 DPpower 恒 1、fan_gear、mode、fault_code),每个业务 tick 调用
* @note DP3/DP4 温湿度在 userHandle500ms)填;DP0 写忽略,运行中恒上报 1
* @return 无
*/
void app_function_poll(void)
{
gDevData.power = (s_func.app_power) ? 1 : 0;
gDevData.fan_gear = app_fan_get_gear(); /* DP2 必须等于当前真实档位 */
gDevData.mode = app_mode_get_active();
/* 规格书 8.2/15:传感器故障优先 2;否则温湿度比较成立报 1 */
if (app_th_is_fault()) {
gDevData.fault_code = 2;
} else if (app_disp_is_alarm()) {
gDevData.fault_code = 1;
} else {
gDevData.fault_code = 0;
}
}
/**
* @brief 停手动 + 模式,风扇关(关机请求 / 软关时用)
* @return 无
*/
void app_function_stop_all(void)
{
app_mode_stop();
app_fan_set_gear(0);
}
/**
* @brief 软关:风扇停、DP0=0(本产品 DP0 写忽略,软关仅按键 3s 触发)
* @return 无
*/
void app_function_soft_off(void)
{
s_func.app_power = 0;
gDevData.power = 0;
app_function_stop_all();
log_info("soft off\n");
}
/**
* @brief 上电默认开启功能(DP0=1),不带开机灯效提示
* @return 无
*/
void app_function_power_on_silent(void)
{
s_func.app_power = 1;
gDevData.power = 1;
}
/**
* @brief 查询功能开关状态(DP0)
* @return 1=开,0=关
*/
uint8_t app_function_is_power_on(void)
{
return s_func.app_power;
}
/**
* @brief 短按:风扇档位循环 1→2→3→0→1…(规格书 5.3)
* @note 立刻退出通风/强力改为手动档:用 app_mode_stop() 只清模式、
* 不动档位(若用 set_manual(0) 会恢复模式前快照档,导致通风 1 档
* 短按跳到旧档+1 而非 2 档);配对进行中短按仍可切档
* @return 无
*/
void usr_on_key_short(void)
{
uint8_t g;
if (app_power_poweroff_pending()) {
return;
}
if (!s_func.app_power) {
/* 软关态短按只唤醒,不切档(P0 无 APP 软关,保留分支) */
s_func.app_power = 1;
gDevData.power = 1;
app_led_hint_power_on();
return;
}
app_arbiter_manual_intervene(); /* 手动动作:释放条件/定时占用(12 章) */
app_mode_stop(); /* 退模式(不动档位,下面立刻切循环下一档) */
g = app_fan_get_gear(); /* 当前实际档:手动=手动档;模式中=模式强制档(1/3) */
g = (uint8_t)((g + 1) % 4); /* 1→2→3→0→1 */
app_fan_set_gear(g);
log_info("key short gear=%d\n", g);
}
/**
* @brief 长按 3s:请求软关机(配对中忽略,避免配到一半睡死,规格书 5.3)
* @note ⚠ 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,禁止直接
* 调 app_power_request_poweroff(其钩子会做 VM 落盘 → 栈溢出)。
* 只置 off_pending,由 app_function_loop(任务上下文)落盘后关机。
* @return 无
*/
void usr_on_key_long(void)
{
if (app_power_poweroff_pending()) {
return;
}
if (app_pair_is_active()) {
log_info("key hold 3s ignored, pairing\n");
return;
}
log_info("key hold 3s, poweroff pending (wait vm flush)\n");
s_func.off_pending = 1;
}
/**
* @brief 出厂重置:清业务 VM 与 RAM,保留 BLE 配对(规格书 14 章)
* @return 无
*/
void app_function_factory_reset(void)
{
uint8_t i;
uint8_t *c[7] = {
gDevData.cond_config1, gDevData.cond_config2, gDevData.cond_config3,
gDevData.cond_config4, gDevData.cond_config5, gDevData.cond_config6,
gDevData.cond_config7
};
uint8_t *tm[7] = {
gDevData.time_config1, gDevData.time_config2, gDevData.time_config3,
gDevData.time_config4, gDevData.time_config5, gDevData.time_config6,
gDevData.time_config7
};
app_nvm_reset();
app_arbiter_init();
app_cond_init();
app_timer_init();
app_mode_stop();
app_fan_set_gear(0);
gDevData.mode = 0;
gDevData.fan_gear = 0;
gDevData.cond_en = 0;
gDevData.time_en = 0;
gDevData.fault_en = 0;
gDevData.alarm_en = 0;
gDevData.fault_code = 0;
gDevData.alarm_code = 0;
for (i = 0; i < 7; i++) {
memset(c[i], 0, 7);
memset(tm[i], 0, 8);
}
log_info("factory reset: business vm cleared, pairing kept\n");
}