接入温湿度风扇产品固件(仲裁/条件/定时/显示),并补齐规格书与外设驱动
新增 usr_app 产品逻辑:手动>定时>条件仲裁、条件控温湿、定时任务、数码管显示、 按键/LED、风扇档位、NVM 掉电恢复、配对与开关机,上电按规格恢复上次状态。 新增 usr_periph:AHT20、CT1642、板级引脚与硬件封装;见宝协议 cond_config 改为 7 字节编解码,并接入产品 DP。 补充《温湿度风扇_固件需求规格书》,工程加入对应源文件。 .gitignore 忽略 WorkBuddy/Cursor 本地会话
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
/******************************************************************************
|
||||
* @file app_mode.c
|
||||
* @brief CBR3 工作模式实现(P1):通风 25/5 循环、强力 15min 一轮
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.08.29
|
||||
* @version V1.1.0
|
||||
* @history
|
||||
* - V1.0.0, 2026.08.29, cyWu, 首次发布(P0 stub)
|
||||
* - V1.1.0, 2026.08.31, cyWu, P1 实现状态机(规格书第 9 章):
|
||||
* 通风 25/5、强力 15min 后停、手动档快照、退出语义、开机从周期头
|
||||
*
|
||||
* @note 模式激活时强制覆盖风扇档位(通风=1 档、强力=3 档、通风停段=0),
|
||||
* DP2 由 app_fan_get_gear 上报真实档位(app_function_poll 同步)。
|
||||
* 退出方式(规格书 9 章):短按切档(app_mode_stop)、APP 写档位、
|
||||
* APP 写 mode=0(恢复进入模式前的手动档快照)、强力自然到点(风扇 0)。
|
||||
* 开机恢复不存相位:从 25min 开段 / 15min 从头计。
|
||||
******************************************************************************/
|
||||
|
||||
#include "app_mode.h"
|
||||
#include "app_fan.h"
|
||||
#include "app_nvm.h"
|
||||
#include "board_pin.h"
|
||||
|
||||
#define LOG_TAG_CONST APP
|
||||
#define LOG_TAG "[APP_MODE]"
|
||||
#define LOG_INFO_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
/** 通风循环段 */
|
||||
typedef enum {
|
||||
MODE_VENT_ON = 0, /**< 开段 25min,强制 1 档 */
|
||||
MODE_VENT_OFF /**< 停段 5min,风扇 0 */
|
||||
} ModeVentPhase_t;
|
||||
|
||||
/** 模式状态机上下文 */
|
||||
typedef struct {
|
||||
uint8_t mode; /**< 0=关闭 1=通风 2=强力 */
|
||||
uint8_t phase; /**< 通风段;其它模式恒 0 */
|
||||
uint32_t run_ms; /**< 当前段已运行毫秒 */
|
||||
uint8_t saved_gear;/**< 进入模式前的手动档快照(APP 写 mode=0 时恢复) */
|
||||
} AppModeCtx_t;
|
||||
|
||||
static AppModeCtx_t s_mode;
|
||||
|
||||
/**
|
||||
* @brief 初始化模式状态机
|
||||
* @return 无
|
||||
*/
|
||||
void app_mode_init(void)
|
||||
{
|
||||
#if !BOARD_MODE_ENABLE
|
||||
log_info("mode disabled\n");
|
||||
return;
|
||||
#endif
|
||||
s_mode.mode = 0;
|
||||
s_mode.phase = 0;
|
||||
s_mode.run_ms = 0;
|
||||
s_mode.saved_gear = 0;
|
||||
log_info("mode init\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 推进模式状态机(每个业务 tick 调用)
|
||||
* @param dt 距上次调用的毫秒数
|
||||
* @return 无
|
||||
*/
|
||||
void app_mode_run(uint16_t dt)
|
||||
{
|
||||
#if !BOARD_MODE_ENABLE
|
||||
(void)dt;
|
||||
return;
|
||||
#endif
|
||||
switch (s_mode.mode) {
|
||||
case 1: /* 通风:开 25min 强制 1 档,停 5min 风扇 0,循环 */
|
||||
if (s_mode.phase == MODE_VENT_ON) {
|
||||
app_fan_set_gear(1);
|
||||
s_mode.run_ms += dt;
|
||||
if (s_mode.run_ms >= BOARD_MODE_VENT_ON_MS) {
|
||||
s_mode.phase = MODE_VENT_OFF;
|
||||
s_mode.run_ms = 0;
|
||||
app_fan_set_gear(0);
|
||||
app_nvm_mark_dirty();
|
||||
log_info("vent on 25min over, off 5min\n");
|
||||
}
|
||||
} else {
|
||||
s_mode.run_ms += dt;
|
||||
if (s_mode.run_ms >= BOARD_MODE_VENT_OFF_MS) {
|
||||
s_mode.phase = MODE_VENT_ON;
|
||||
s_mode.run_ms = 0;
|
||||
app_fan_set_gear(1);
|
||||
app_nvm_mark_dirty();
|
||||
log_info("vent off 5min over, on 25min\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* 强力:强制 3 档,15min 到点风扇 0、mode 回 0 */
|
||||
app_fan_set_gear(3);
|
||||
s_mode.run_ms += dt;
|
||||
if (s_mode.run_ms >= BOARD_MODE_POWER_ON_MS) {
|
||||
log_info("power 15min over, mode=0 fan=0\n");
|
||||
s_mode.mode = 0;
|
||||
s_mode.phase = 0;
|
||||
s_mode.run_ms = 0;
|
||||
app_fan_set_gear(0);
|
||||
app_nvm_mark_dirty();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief APP 写 DP1 / 手动抢权 / 开机恢复:切到指定模式或退出
|
||||
* @param mode 0=关闭模式(恢复手动档快照),1=通风,2=强力
|
||||
* @note 模式 1/2 进入时快照当前实际档(即进入前的手动档),并立即强制档位;
|
||||
* mode=0 时若原在模式中则恢复快照档。短按退出走 app_mode_stop()
|
||||
* (不恢复快照,档位由短按逻辑立刻切到循环下一档)。
|
||||
* @return 无
|
||||
*/
|
||||
void app_mode_set_manual(uint8_t mode)
|
||||
{
|
||||
#if !BOARD_MODE_ENABLE
|
||||
(void)mode;
|
||||
return;
|
||||
#endif
|
||||
if (mode > 2) {
|
||||
mode = 0;
|
||||
}
|
||||
if (mode != 0) {
|
||||
s_mode.saved_gear = app_fan_get_gear(); /* 快照进入前的手动档 */
|
||||
s_mode.mode = mode;
|
||||
s_mode.phase = MODE_VENT_ON;
|
||||
s_mode.run_ms = 0; /* 不存相位:开机/手动切入都从周期头计 */
|
||||
app_fan_set_gear((mode == 1) ? 1 : 3);
|
||||
log_info("mode set %d, gear=%d\n", mode, app_fan_get_gear());
|
||||
} else {
|
||||
if (s_mode.mode != 0) {
|
||||
/* 只在实际退出模式时恢复快照档,避免 load(0) 把恢复档清零 */
|
||||
app_fan_set_gear(s_mode.saved_gear);
|
||||
log_info("mode exit, restore gear=%d\n", s_mode.saved_gear);
|
||||
}
|
||||
s_mode.mode = 0;
|
||||
s_mode.phase = 0;
|
||||
s_mode.run_ms = 0;
|
||||
}
|
||||
app_nvm_mark_dirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 查询当前逻辑模式
|
||||
* @return 0/1/2
|
||||
*/
|
||||
uint8_t app_mode_get_active(void)
|
||||
{
|
||||
return s_mode.mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停止当前模式(短按退模式用:只清模式状态,不动风扇档位,
|
||||
* 由调用方立刻切到循环下一档;关机流程则另行停风扇)
|
||||
* @return 无
|
||||
*/
|
||||
void app_mode_stop(void)
|
||||
{
|
||||
#if !BOARD_MODE_ENABLE
|
||||
return;
|
||||
#endif
|
||||
if (s_mode.mode != 0) {
|
||||
app_nvm_mark_dirty();
|
||||
}
|
||||
s_mode.mode = 0;
|
||||
s_mode.phase = 0;
|
||||
s_mode.run_ms = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user