Files
wuchuyuan 59361cd9d5 增加LED状态显示功能:
1、设备上电红灯红灯常亮
2、设备连接上COM口红灯闪烁
3、设备连接上BLE绿灯常亮
4、设备进入OTA绿灯闪烁
2026-08-03 14:53:46 +08:00

263 lines
7.2 KiB
C
Raw Permalink 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 usr_led_status.c
* @brief 状态指示灯实现
* @author cyWu <1917507415@qq.com>
* @date 2026.08.03
* @version V1.0.0
* @history
* - V1.0.0, 2026.08.03, cyWu, 首次发布
*
* 显示规则:
* 红灯(PA8):上电常亮;COM(DTR)打开时 1Hz 闪烁(优先于常亮)
* 绿灯(PA7)BLE 已连接常亮;OTA 进行中 1Hz 闪烁(优先于常亮);否则熄灭
*
* 依赖:
* - BLEusr_get_conn_service() != 0
* - COMcdc_is_com_open() == 1(与 Dengle 暂停语义一致)
* - OTAusr_get_ota_status() == 0dual_ota_idle=0 表示忙)
******************************************************************************/
#include "system/includes.h"
#include "app_config.h"
#include "asm/gpio.h"
#include "usr_led_status.h"
#if TCFG_USB_SLAVE_CDC_ENABLE
#include "usb/device/cdc.h"
#endif
#define LOG_TAG_CONST APP
#define LOG_TAG "[LED]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
/*============================================================================*/
/* 私有宏 (Private macros) */
/*============================================================================*/
#define USR_LED_GREEN_PIN IO_PORTA_07 /**< 绿灯 */
#define USR_LED_RED_PIN IO_PORTA_08 /**< 红灯 */
/**
* LED 点亮电平:1=高电平点亮,0=低电平点亮
* 若实测灯反了,改此宏即可
*/
#define USR_LED_ON_LEVEL (0)
#define USR_LED_OFF_LEVEL (!(USR_LED_ON_LEVEL))
#define USR_LED_BLINK_HALF_MS (500) /**< 1Hz:亮/灭各 500ms */
#define USR_LED_HALF_TICKS (USR_LED_BLINK_HALF_MS / USR_LED_TICK_MS)
/*============================================================================*/
/* 私有类型 (Private types) */
/*============================================================================*/
typedef enum {
LED_MODE_OFF = 0,
LED_MODE_ON,
LED_MODE_BLINK
} LedMode_t;
/*============================================================================*/
/* 私有变量 (Private variables) */
/*============================================================================*/
static uint8_t s_initialized = 0;
static u16 s_tick_timer = 0;
static uint8_t s_blink_phase = 0; /**< 0=半周期灭侧,1=半周期亮侧 */
static uint8_t s_blink_cnt = 0; /**< 半周期内已走过的 tick 数 */
extern u16 usr_get_conn_service(void);
extern u8 usr_get_ota_status(void);
/*============================================================================*/
/* 私有函数声明 (Private function prototypes) */
/*============================================================================*/
static void usr_led_gpio_init(u32 pin);
static void usr_led_set(u32 pin, uint8_t on);
static uint8_t usr_led_is_com_open(void);
static uint8_t usr_led_is_ble_conn(void);
static uint8_t usr_led_is_ota_busy(void);
static void usr_led_apply(u32 pin, LedMode_t mode);
static void usr_led_tick(void *priv);
/*============================================================================*/
/* 公有函数实现 (Public API implementation) */
/*============================================================================*/
/**
* @brief 初始化状态灯
* @return UsrLed_Ret_t 错误码
*/
UsrLed_Ret_t usr_led_status_init(void)
{
if (s_initialized) {
return USR_LED_OK;
}
usr_led_gpio_init(USR_LED_GREEN_PIN);
usr_led_gpio_init(USR_LED_RED_PIN);
/* 上电:红灯常亮,绿灯熄灭 */
usr_led_set(USR_LED_RED_PIN, 1);
usr_led_set(USR_LED_GREEN_PIN, 0);
s_blink_phase = 1;
s_blink_cnt = 0;
s_initialized = 1;
if (s_tick_timer == 0) {
s_tick_timer = sys_timer_add(NULL, usr_led_tick, USR_LED_TICK_MS);
}
printf("usr_led_status_init ok (red=PA8 green=PA7)\n");
return USR_LED_OK;
}
/**
* @brief 主处理:刷新红/绿灯显示模式
*/
void usr_led_status_run(void)
{
LedMode_t red_mode;
LedMode_t green_mode;
if (!s_initialized) {
return;
}
/* 红灯:COM 打开 → 闪烁;否则上电常亮 */
if (usr_led_is_com_open()) {
red_mode = LED_MODE_BLINK;
} else {
red_mode = LED_MODE_ON;
}
/* 绿灯:OTA 忙 → 闪烁;BLE 已连 → 常亮;否则熄灭 */
if (usr_led_is_ota_busy()) {
green_mode = LED_MODE_BLINK;
} else if (usr_led_is_ble_conn()) {
green_mode = LED_MODE_ON;
} else {
green_mode = LED_MODE_OFF;
}
/* 任一灯在闪时推进公共 1Hz 相位,保证同频同相 */
if (red_mode == LED_MODE_BLINK || green_mode == LED_MODE_BLINK) {
s_blink_cnt++;
if (s_blink_cnt >= USR_LED_HALF_TICKS) {
s_blink_cnt = 0;
s_blink_phase ^= 1;
}
} else {
s_blink_cnt = 0;
s_blink_phase = 1;
}
usr_led_apply(USR_LED_RED_PIN, red_mode);
usr_led_apply(USR_LED_GREEN_PIN, green_mode);
}
/**
* @brief 获取当前初始化状态
* @return UsrLed_Ret_t
*/
UsrLed_Ret_t usr_led_status_get_status(void)
{
if (!s_initialized) {
return USR_LED_ERR_NOT_INIT;
}
return USR_LED_OK;
}
/*============================================================================*/
/* 私有函数实现 (Private functions) */
/*============================================================================*/
/**
* @brief 配置 LED 引脚为推挽输出
* @param pin GPIO 宏(如 IO_PORTA_07
*/
static void usr_led_gpio_init(u32 pin)
{
gpio_set_die(pin, 1);
gpio_set_pull_up(pin, 0);
gpio_set_pull_down(pin, 0);
gpio_direction_output(pin, USR_LED_OFF_LEVEL);
}
/**
* @brief 点亮/熄灭指定 LED
* @param pin GPIO
* @param on 1=亮,0=灭
*/
static void usr_led_set(u32 pin, uint8_t on)
{
gpio_direction_output(pin, on ? USR_LED_ON_LEVEL : USR_LED_OFF_LEVEL);
}
/**
* @brief COM 口是否打开(CDC DTR
* @return 1=已打开,0=未打开/无 CDC
*/
static uint8_t usr_led_is_com_open(void)
{
#if TCFG_USB_SLAVE_CDC_ENABLE
return cdc_is_com_open() ? 1 : 0;
#else
return 0;
#endif
}
/**
* @brief BLE 是否已连接
* @return 1=已连接
*/
static uint8_t usr_led_is_ble_conn(void)
{
return (usr_get_conn_service() != 0) ? 1 : 0;
}
/**
* @brief 是否正在 OTAusr_get_ota_status==0 表示忙)
* @return 1=OTA 进行中
*/
static uint8_t usr_led_is_ota_busy(void)
{
return (usr_get_ota_status() == 0) ? 1 : 0;
}
/**
* @brief 按模式驱动单灯
* @param pin GPIO
* @param mode 灭 / 常亮 / 闪烁
*/
static void usr_led_apply(u32 pin, LedMode_t mode)
{
switch (mode) {
case LED_MODE_ON:
usr_led_set(pin, 1);
break;
case LED_MODE_BLINK:
usr_led_set(pin, s_blink_phase);
break;
case LED_MODE_OFF:
default:
usr_led_set(pin, 0);
break;
}
}
/**
* @brief sys_timer 回调:100ms 刷新一次
* @param priv 未使用
*/
static void usr_led_tick(void *priv)
{
(void)priv;
usr_led_status_run();
}