Files
JBao_Door_Clamp_FW/apps/usr_app/app_led.c
T
wuchuyuan fdb43011b7 1、低电 3.7V 只闪红灯不再 1 分钟后关机;电量低于约 5% 自动关机,未充电开机先闪 5 下红灯再睡回,只能充电后才能开机
2、自动/手动互相切换都闪 2 下灯;APP 发停止后再发自动模式可正常启动,手动残留停止不再挡住自动
3、自动模式 1~6 单次最长跑 10 分钟后回待机;关机时长按 12 秒进 OTA,OTA 期间红绿交替闪
2026-08-27 10:20:48 +08:00

254 lines
7.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/******************************************************************************
* @file app_led.c
* @brief CBC2 灯效适配:充电红与待机绿可同时亮,不再 if-else 互斥
* @author cyWu <1917507415@qq.com>
* @date 2026.08.25
* @version V2.0.0
* @history
* - V1.0.0, 2026.08.21, cyWu, 首次发布
* - V1.1.0, 2026.08.25, cyWu, 开机绿灯只提示几秒
* - V2.0.0, 2026.08.25, cyWu, 改用 LED 事件表,红绿通道独立
* - V2.1.0, 2026.08.25, cyWu, 自己从 app_power/app_pair 取数并内部组装
* - V2.2.0, 2026.08.25, cyWu, 重启/清场逻辑各提一个小函数,把意图写进注释
* - V2.3.0, 2026.08.27, cyWu, 新增 OTA 红绿交替灯效
******************************************************************************/
#include "app_led.h"
#include "led_manager.h"
#include "bsp_hw.h"
#include "board_pin.h"
#include "app_power.h"
#include "app_pair.h"
static uint8_t s_initialized;
static uint8_t s_ota; /* 1=OTA 灯效中,app_led_run 不再叠其它灯 */
static void led_start_pair_result(uint8_t ok);
/**
* @brief 重新播放一次「一次性/限时」灯效,让它从第 0 帧重新开始
* @note led.c 的 LED_EventAdd 只有在“该优先级槽位当前不是这个事件”时才会把
* currentTime 重置为现在;如果动画正播到一半直接再 Add 一次,事件已经
* 占着槽位,不会重置,会接着上次的进度走。所以要先 Delete 清空槽位,
* 再 Add 才能强制重新计时——这不是多余代码,是“重启”这个事件的手段。
* @param evt 要重启的事件(切模式闪、开机绿灯提示、配对结果)
* @return 无
*/
static void led_restart(LED_Event_t evt)
{
LED_EventDelete(evt);
LED_EventAdd(evt);
}
/**
* @brief 绿灯正被切模式/配对结果占用(不含配对快闪本身)
* @return 1=绿灯忙
*/
static uint8_t green_pattern_busy(void)
{
return (uint8_t)(LED_IsEventExist(LED_EVENT_MODE)
|| LED_IsEventExist(LED_EVENT_PAIR_OK)
|| LED_IsEventExist(LED_EVENT_PAIR_FAIL));
}
/**
* @brief 绿灯正被配对/切模式/结果占用时,不要再挂待机绿
* @return 1=绿灯忙
*/
static uint8_t green_busy(void)
{
return (uint8_t)(LED_IsEventExist(LED_EVENT_PAIRING) || green_pattern_busy());
}
/**
* @brief 灯效初始化
* @return APP_LED_OK=成功
*/
AppLed_Ret_t app_led_init(void)
{
if (s_initialized) {
return APP_LED_OK;
}
user_led_init();
s_initialized = 1;
return APP_LED_OK;
}
/**
* @brief 查询模块是否已初始化
* @return APP_LED_OK=已初始化,APP_LED_ERR_NOT_INIT=未初始化
*/
AppLed_Ret_t app_led_get_status(void)
{
return s_initialized ? APP_LED_OK : APP_LED_ERR_NOT_INIT;
}
/**
* @brief 请求切模式绿灯闪两下(与配对灯同优先级,会盖住配对闪)
* @return 无
*/
void app_led_request_mode_blink(void)
{
if (!s_initialized || s_ota) {
return;
}
led_restart(LED_EVENT_MODE);
}
/**
* @brief 重新挂待机绿灯(常亮或提示几秒,看 BOARD_LED_STANDBY_ON
* @return 无
*/
void app_led_hint_power_on(void)
{
if (!s_initialized || s_ota) {
return;
}
led_restart(LED_EVENT_STANDBY);
}
/**
* @brief 进入 OTA:清掉其它灯,挂红绿交替一直闪
* @return 无
*/
void app_led_request_ota(void)
{
if (!s_initialized) {
return;
}
s_ota = 1;
LED_EventAllDelete();
bsp_led_all_off();
LED_EventAdd(LED_EVENT_OTA);
}
/**
* @brief 查询是否处于 OTA 灯效
* @return 1=OTA 灯效中,0=否
*/
uint8_t app_led_is_ota(void)
{
return s_ota;
}
/**
* @brief 播放一次性配对结果灯
* @param ok 1=成功常绿,0=失败红绿交替
* @return 无
*/
static void led_start_pair_result(uint8_t ok)
{
LED_EventDelete(LED_EVENT_PAIRING); /* 结果灯盖住配对快闪 */
led_restart(ok ? LED_EVENT_PAIR_OK : LED_EVENT_PAIR_FAIL);
}
/**
* @brief 功能关闭(DP0=0)时清掉所有“功能相关”的灯事件
* @note 故意不用 LED_EventAllDelete():那会把优先级表全清空,连充电红/满灯
* LED_EVENT_CHARGE / LED_EVENT_CHARGE_FULL)也会跟着灭掉。但充电状态
* 和 DP0 开关是两码事——设备功能关着也可能正在充电,充电灯必须继续亮,
* 所以这里只挑功能相关的几个事件逐个删,充电事件不动它。
* @return 无
*/
static void led_clear_function_events(void)
{
LED_EventDelete(LED_EVENT_STANDBY);
LED_EventDelete(LED_EVENT_PAIRING);
LED_EventDelete(LED_EVENT_MODE);
LED_EventDelete(LED_EVENT_PAIR_OK);
LED_EventDelete(LED_EVENT_PAIR_FAIL);
LED_EventDelete(LED_EVENT_LOWBAT);
}
/**
* @brief 按优先级刷新灯:充电/低电从 app_power 取,配对从 app_pair 取,
* 只有“功能是否开”这一项由调用方传入
* @param dt 距上次调用的毫秒数
* @param app_power 1=功能开(DP0),0=功能关,功能灯全灭
* @return 无
*/
void app_led_run(uint16_t dt, uint8_t app_power)
{
uint8_t charge_led;
uint8_t low_bat;
uint8_t pairing;
uint8_t func_on;
AppPairEvt_t pair_evt;
if (!s_initialized) {
return;
}
/* OTA 期间只跑红绿交替,充电/待机/配对都不要叠上去 */
if (s_ota) {
LED_EventAdd(LED_EVENT_OTA);
user_led_handle();
return;
}
/* 配对成功/失败是边沿事件,只在那一拍切灯效 */
pair_evt = app_pair_tick_1ms(dt);
if (pair_evt == APP_PAIR_EVT_OK) {
led_start_pair_result(1);
} else if (pair_evt == APP_PAIR_EVT_FAIL) {
led_start_pair_result(0);
}
charge_led = app_power_charge_led();
low_bat = app_power_low_bat();
func_on = app_power ? 1 : 0;
pairing = (uint8_t)(app_pair_is_active() && func_on);
/* 充电红 / 充满绿:和功能开关无关,关着设备也可能在充电 */
if (charge_led == 1) {
LED_EventAdd(LED_EVENT_CHARGE);
} else {
LED_EventDelete(LED_EVENT_CHARGE);
}
if (charge_led == 2) {
LED_EventAdd(LED_EVENT_CHARGE_FULL);
} else {
LED_EventDelete(LED_EVENT_CHARGE_FULL);
}
/* 绿灯正被切模式/配对结果占用时,不要再挂配对快闪,避免互相覆盖 */
if (pairing && !green_pattern_busy()) {
LED_EventAdd(LED_EVENT_PAIRING);
} else if (!pairing) {
LED_EventDelete(LED_EVENT_PAIRING);
}
/* 低电红闪:只在功能开、没接电时才挂,充电红优先 */
if (func_on && low_bat && (charge_led == 0)) {
LED_EventAdd(LED_EVENT_LOWBAT);
} else {
LED_EventDelete(LED_EVENT_LOWBAT);
}
if (!func_on) {
led_clear_function_events();
} else {
#if BOARD_LED_STANDBY_ON
/* 正在充电(红)或已充满(绿)时都不叠加待机绿,只有完全没接电才显示待机 */
if ((charge_led == 0) && !pairing && !green_busy()) {
LED_EventAdd(LED_EVENT_STANDBY);
} else {
LED_EventDelete(LED_EVENT_STANDBY);
}
#endif
}
user_led_handle();
}
/**
* @brief 清空全部灯事件并灭灯
* @return 无
*/
void app_led_clear(void)
{
LED_EventAllDelete();
bsp_led_all_off();
}