杰理 SDK 文档中心
首页
首页
  • SDK 概述与入门

    • SDK 总览
    • 支持芯片与蓝牙认证
    • 工程结构导航
  • 开发环境与构建

    • 环境搭建与工具链安装
    • 编译指南与工程选择
    • 烧录与生产工具
  • BLE 透传/数传应用

    • 透传应用框架与处理模块
    • 透传与数传示例
    • 多连接与自定义服务示例
    • FindMy 与查找网络示例
  • HID 人机交互应用

    • 键盘与按键设备示例
    • 鼠标设备示例
    • 遥控器示例
    • HID 蓝牙应用模块
  • 公共 BSP 模块

    • 按键、编码器与红外输入
    • 传感器驱动
    • LED 与显示控制
    • 串口与 USB 通信
    • 存储、参数与时钟
    • 电源与温度管理
    • 消息、内存与系统配置
    • OTA 升级框架
  • 蓝牙协议栈与库

    • BLE 控制器与协议栈适配
    • 经典蓝牙 BR/EDR 支持
    • 第三方蓝牙协议
    • 设备管理框架
    • DUT 测试与射频认证
  • 构建系统与开发工具

    • Makefile 构建系统
    • 固件后处理与配置工具
    • 辅助脚本与库合并
  • 文档与硬件资料

    • AT 命令参考
    • 硬件参考资料
    • SDK 文档与在线资源

遥控器示例

本页面介绍 AW33N BLE SDK 中基于 BLE HID(人机交互设备)的遥控器(Remote Control)示例应用,涵盖其 HID 报告映射、按键处理、红外(IR)联动、低功耗关机、BLE 重连与配对等完整实现机制。

Purpose and Scope

本文档面向希望在 AW33N 平台上快速实现遥控器类产品(如电视遥控器、机顶盒遥控器)的嵌入式开发者,完整说明 apps/demo/hid/examples/remote_control/app_remote_control.c 的实现:

  • 本页覆盖:BLE HID Consumer 报告定义、按键→消费类按键码映射、BLE/IR 双通道发送策略、自动关机定时、BLE 配对/断开逻辑、应用状态机与消息循环、相关板级配置。
  • 不在本页范围:BLE HOGP 协议栈底层实现(见 ble_hogp 模块)、红外编码器硬件驱动(ir_encoder)、通用 HID 协议(standard_hid)以及 LED 控制框架(led_control)——这些由各自的模块文档说明。
  • 相关示例:同目录下还有鼠标(mouse)、键盘(keyboard)等其他 HID 示例,本页仅聚焦遥控器示例。

概述

遥控器示例是 SDK 中一个可直接编译运行的 BLE HID 应用:设备以 BLE_APPEARANCE_GENERIC_REMOTE_CONTROL 外观广播,通过 Consumer Control(消费类控制,Usage Page 0x0C) 报告向主机(电视/机顶盒/手机)发送音量、播放暂停、静音、切歌、快进快退等按键,同时支持 红外(IR)发射(示例中码表匹配海信电视),实现"BLE 优先、IR 兜底"的双模遥控方案。

设计上该示例解决了遥控器产品的几个核心诉求:

  1. 低功耗:无操作一段时间后自动软关机(TCFG_HID_AUTO_SHUTDOWN_TIME),软关机前确保蓝牙链路断开。
  2. 双通道兼容:BLE 未连接时用 IR 控制旧设备,BLE 已连接时优先走 BLE(电源键除外,始终走 IR)。
  3. 易配对:双击指定按键触发断开并重新进入可配对状态;三击进入软关机。
  4. 平台无关的按键抽象:通过 hidrc_click_table / hidrc_hold_table 把 AD 按键值映射为消费类按键码,换按键矩阵只需改表。

架构

flowchart TD
    subgraph sg_HW["硬件层"]
        KEY["AD按键 (TCFG_ADKEY_VALUEx)"]
        LED["LED指示灯"]
        IR_TX["红外发射管"]
        BLE_RF["BLE射频"]
    end

    subgraph sg_APP["遥控器应用 (app_remote_control.c)"]
        SM["hidrc_state_machine<br/>APP状态机"]
        MSG["消息循环<br/>get_msg + app_comm_process_handler"]
        KEY_DEAL["hidrc_app_key_deal_test<br/>按键分发"]
        IR_DEAL["hidrc_ir_key_deal<br/>IR按键处理"]
        BLE_SEND["ble_hid_data_send<br/>HID上报"]
        PWR["hidrc_set_soft_poweroff<br/>软关机"]
        TIMER["hidrc_auto_shutdown_timer<br/>自动关机定时器"]
    end

    subgraph sg_SDK["SDK服务"]
        HOGP["HOGP (ble_hogp)"]
        BTSTACK["btstack (btstack_task)"]
        IR_ENC["ir_encoder"]
        LED_CTL["led_control"]
        PWR_MG["app_power_mg"]
        SYS_TMR["sys_timer"]
    end

    KEY --> KEY_DEAL
    KEY_DEAL --> BLE_SEND
    KEY_DEAL --> IR_DEAL
    IR_DEAL --> IR_ENC
    IR_ENC --> IR_TX
    BLE_SEND --> HOGP
    HOGP --> BTSTACK
    BTSTACK --> BLE_RF
    SM --> MSG
    MSG --> KEY_DEAL
    MSG --> PWR
    TIMER --> PWR
    PWR --> BTSTACK
    PWR --> PWR_MG
    KEY_DEAL --> LED_CTL
    LED_CTL --> LED

架构说明

  • 应用层(本页主体):app_remote_control.c 定义了一个完整应用,包含状态机、消息循环、按键分发、BLE 配置与 IR 配置。它不直接操作寄存器,而是通过 SDK 服务模块完成功能。
  • HOGP 服务:负责 BLE HID over GATT Profile 的初始化(hogp_bt_ble_init)与广播(hogp_bt_ble_before_start_init),应用通过 ble_hid_data_send() 发送报告、le_hogp_* 系列接口控制配对与断开。
  • IR 编码器:ir_encoder 负责把操作码编码为红外波形,ir_encoder_tx_hx(0, cmd, is_long) 是发送入口,ir_encoder_repeat_stop() 停止重复发送。
  • 电源管理:自动关机定时器到期后投递 POWER_EVENT_POWER_SOFTOFF 事件,软关机流程区分 SOFT_MODE(不必等待断链)与 SOFT_BY_POWER_MODE(必须等待断链)两种低功耗模式。
  • LED 控制:按键反馈(LED_KEY_UP)与开机闪灯(LED_INIT_FLASH)由 led_control 服务统一调度。

核心实现分析

1. HID 消费类报告映射表

报告描述符定义在 hidrc_report_map 中,仅 35 字节,使用 Consumer 页(0x0C),Report ID 为 1,16 个 1-bit 开关量分别对应音量加/减、播放暂停、静音、上一曲/下一曲、快进/快退:

static const uint8_t hidrc_report_map[] = {
    0x05, 0x0C,        // Usage Page (Consumer)
    0x09, 0x01,        // Usage (Consumer Control)
    0xA1, 0x01,        // Collection (Application)
    0x85, 0x01,        //   Report ID (1)
    0x09, 0xE9,        //   Usage (Volume Increment)
    0x09, 0xEA,        //   Usage (Volume Decrement)
    0x09, 0xCD,        //   Usage (Play/Pause)
    0x09, 0xE2,        //   Usage (Mute)
    0x09, 0xB6,        //   Usage (Scan Previous Track)
    0x09, 0xB5,        //   Usage (Scan Next Track)
    0x09, 0xB3,        //   Usage (Fast Forward)
    0x09, 0xB4,        //   Usage (Rewind)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x10,        //   Report Count (16)
    0x81, 0x02,        //   Input (Data,Var,Abs,...)
    0xC0,              // End Collection
    // 35 bytes
};

Source: app_remote_control.c

设计意图:每个消费类按键占用 1 bit,报告长度为 2 字节(16 bit),按键按下时置位对应 bit,松开时清零,通过 ble_hid_data_send(1, &key_msg, 2) 以 Report ID=1 发送。这种"位图"式报告比 8-bit 数组更紧凑,且天然支持多键同时按下(组合键)。

2. 按键码映射表

hidrc_click_table(单击)与 hidrc_hold_table(长按)把 AD 按键的物理序号映射为消费类按键码,下标即键值 key_value:

static const uint16_t hidrc_click_table[10] = {
    0,                          // 0: 无功能
    CONSUMER_SCAN_PREV_TRACK,   // 1: 上一曲
    CONSUMER_MUTE,              // 2: 静音
    CONSUMER_VOLUME_DEC,        // 3: 音量减
    CONSUMER_PLAY_PAUSE,        // 4: 播放/暂停
    CONSUMER_VOLUME_INC,        // 5: 音量加
    0,
    CONSUMER_SCAN_NEXT_TRACK,   // 7: 下一曲
    0,
    0,
};

static const uint16_t hidrc_hold_table[10] = {
    0, 0, 0,
    CONSUMER_VOLUME_DEC,        // 3: 长按连续音量减
    0,
    CONSUMER_VOLUME_INC,        // 5: 长按连续音量加
    0, 0, 0, 0,
};

Source: app_remote_control.c

设计意图:将"物理按键"与"功能"解耦——产品改键位时只改表不改逻辑。长按表只对音量键生效(持续发送音量码实现连续调节),其余键长按不重复发送。

3. 红外码表与 BLE/IR 联动策略

hidrc_ir_cmd_tab 是匹配海信电视的红外 cmd 码表,与 click_table 的键位一一对应;IR_POWER_CMD_VALUE (0x0d) 是电源键特殊值:

const uint8_t hidrc_ir_cmd_tab[] = { // 红外cmd码表,匹配海信电视
    0x14, // menu
    0x16, // up
    0,
    /* 0x19, // left */
    /* 0x18, // right */
    0x43, // vol down
    0x15, // confirm
    0x44, // vol up
    0x48, // return
    0x17, // down
    0x94, // main page
    0,
    0x0d, // power
};

static void hidrc_ir_key_deal(uint8_t key_value, uint8_t key_type)
{
    // ir test
    uint8_t cmd = hidrc_ir_cmd_tab[key_value];
    if (!cmd) {
        return;
    }
    // use ble control if connected,except power cmd
    if (cmd != IR_POWER_CMD_VALUE && ble_hid_is_connected()) {
        return;
    }
    if (key_type == KEY_EVENT_CLICK) {
        hidrc_send_ir_key(cmd, 0);
    } else if (key_type == KEY_EVENT_HOLD) {
        hidrc_send_ir_key(cmd, 1);
    } else if (key_type == KEY_EVENT_UP) {
        ir_encoder_repeat_stop();
    }
}

Source: app_remote_control.c

设计意图:这是典型的"BLE 优先、IR 兜底"策略——BLE 已连接时除电源键外全部走 BLE(IR 码表只用于兼容无 BLE 的老电视),电源键永远走 IR(保证电视可被"物理"关机)。KEY_EVENT_UP 时调用 ir_encoder_repeat_stop() 停止长按导致的重复波形。

4. 按键综合处理与配对/关机快捷操作

hidrc_app_key_deal_test 是按键事件的总入口,按 key_type(单击/长按/抬起/双击/三击)分发:

static void hidrc_app_key_deal_test(uint8_t key_type, uint8_t key_value)
{
    uint16_t key_msg = 0;
    uint16_t key_msg_up = 0;

#if TCFG_IR_ENABLE
    hidrc_ir_key_deal(key_value, key_type);
#endif

#if TCFG_LED_ENABLE
    led_operate(LED_KEY_UP);
#endif

    if (key_type == KEY_EVENT_CLICK) {
        key_msg = hidrc_click_table[key_value];
    } else if (key_type == KEY_EVENT_HOLD) {
        key_msg = hidrc_hold_table[key_value];
    } else if (key_type == KEY_EVENT_UP) {
        log_info("key_up_val = %02x\n", key_value);
        ble_hid_data_send(1, (uint8_t *)&key_msg_up, 2);   // 松开:发送全0报告
        return;
    }

    if (key_msg) {
        log_info("key_msg = %02x\n", key_msg);
        ble_hid_data_send(1, (uint8_t *)&key_msg, 2);      // 按下:发送置位报告
        if (KEY_EVENT_HOLD != key_type) {
            ble_hid_data_send(1, (uint8_t *)&key_msg_up, 2); // 单击:立即补发松开
        }
        return;
    }

    if (key_type == KEY_EVENT_DOUBLE_CLICK && key_value == TCFG_ADKEY_VALUE1) {
        if (ble_hid_is_connected()) {
            le_hogp_disconnect();
        }
        le_hogp_set_pair_allow();   // 进入可配对
        return;
    }

    if (key_type == KEY_EVENT_TRIPLE_CLICK
        && (key_value == TCFG_ADKEY_VALUE3 || key_value == TCFG_ADKEY_VALUE0)) {
        app_power_event_to_user(POWER_EVENT_POWER_SOFTOFF); // 三击软关机
        return;
    }
}

Source: app_remote_control.c

关键行为梳理:

  • 单击:发送置位报告后立即补发全 0 报告,模拟"按下→松开"的完整键动作,避免主机认为按键被卡住。
  • 长按:只发送一次置位报告(不补松开),由主机侧按重复扫描处理连续调节;松开时在 KEY_EVENT_UP 分支发送全 0。
  • 双击(键值 1):先断开当前 BLE 连接再允许配对——这是重新配对(re-pair)的标准流程。
  • 三击(键值 3 或 0):投递 POWER_EVENT_POWER_SOFTOFF 软关机事件。

5. 应用启动、BLE 初始化与自动关机

hidrc_app_start() 是应用真正入口:设置系统/低速/SPI Flash 时钟、初始化蓝牙与 IR/LED,注册自动关机定时器,然后进入消息循环:

static void hidrc_app_start()
{
    log_info("-------------HID_RC DEMO-----------------");
    clk_set("sys", TCFG_CLOCK_SYS_HZ);
    clk_set("lsb", TCFG_CLOCK_LSB_HZ);
    clk_set("sfc", TCFG_CLOCK_SFC_HZ);

    clock_bt_init();
    hidrc_app_bt_start();

#if TCFG_LED_ENABLE
    led_operate(LED_INIT_FLASH);
#endif

#if TCFG_IR_ENABLE
    ir_encoder_init(IR_KEY_IO, IR_WORK_FRQ, IR_WORK_DUTY);
#endif

#if (TCFG_HID_AUTO_SHUTDOWN_TIME)
    //无操作定时软关机
    hidrc_auto_shutdown_timer = sys_timeout_add((void *)POWER_EVENT_POWER_SOFTOFF,
                                                (void *)app_power_event_to_user,
                                                TCFG_HID_AUTO_SHUTDOWN_TIME * 1000);
#endif
    int msg[4] = {0};
    while (1) {
        get_msg(sizeof(msg) / sizeof(int), msg);
        app_comm_process_handler(msg);
    }
}

Source: app_remote_control.c

BLE 初始化细节在 hidrc_app_bt_start() 中,其中 hidrc_ble_config 把 HOGP 的初始化/广播/退出钩子与遥控器报告绑定在一起:

static const ble_init_cfg_t hidrc_ble_config = {
    .same_address = 0,
    .appearance = BLE_APPEARANCE_GENERIC_REMOTE_CONTROL,
    .report_map = hidrc_report_map,
    .report_map_size = sizeof(hidrc_report_map),
    .ble_profile_init = comm_ble_profile_init,
    .bt_ble_init  = hogp_bt_ble_init,
    .bt_ble_before_start_init = hogp_bt_ble_before_start_init,
    .bt_ble_exit = hogp_bt_ble_exit,
    .ble_module_enable = hogp_ble_module_enable,
};

static void hidrc_app_bt_start()
{
    u32 sys_clk =  clk_get("sys");
    bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0);

    btstack_ble_start_before_init(&hidrc_ble_config, 0);
    le_hogp_set_reconnect_adv_cfg(ADV_DIRECT_IND_LOW, 5000); // 回连广播
    le_hogp_set_output_callback(hidrc_recv_callback);

    btstack_init();
}

Source: [app_remote_control.c](https://gitee.com/Jieli-Tech/fw-AW33N_BLE_SDK/blob/master/apps/demo/hid/examples/remote_control/app_remote_control.c#L134-L144, L312-L323)

要点:

  • appearance 声明为通用遥控器外观,主机(如电视)据此显示正确的图标与配对界面。
  • le_hogp_set_reconnect_adv_cfg(ADV_DIRECT_IND_LOW, 5000):断链后以定向广播(仅对已配对主机可见)回连,持续 5000 ms。
  • le_hogp_set_output_callback(hidrc_recv_callback):注册下行通道(主机→设备,如电视向遥控器回传数据)回调。
  • 自动关机定时器使用 sys_timeout_add,回调直接复用 app_power_event_to_user,到期即投递软关机事件;hidrc_auto_shutdown_disable() 可删除该定时器。

核心流程

按键→发送 完整时序

sequenceDiagram
    participant K as "AD按键中断"
    participant APP as "hidrc_app_key_deal_test"
    participant IR as "ir_encoder"
    participant LED as "led_control"
    participant HID as "HOGP (ble_hogp)"
    participant HOST as "BLE主机(电视/机顶盒)"

    K->>APP: 按键事件(key_type, key_value)
    APP->>LED: led_operate(LED_KEY_UP)
    alt TCFG_IR_ENABLE
        APP->>IR: hidrc_ir_key_deal(key_value, key_type)
        alt BLE已连接且非电源键
            IR-->>APP: 跳过(return)
        else BLE未连接或电源键
            IR->>IR: ir_encoder_tx_hx(0, cmd, is_long)
        end
    end
    alt KEY_EVENT_CLICK
        APP->>HID: ble_hid_data_send(1, &key_msg, 2)
        HID->>HOST: 置位报告(bit=1)
        APP->>HID: ble_hid_data_send(1, &key_msg_up, 2)
        HID->>HOST: 全0报告(bit=0)
    else KEY_EVENT_HOLD
        APP->>HID: ble_hid_data_send(1, &key_msg, 2)
        HID->>HOST: 置位报告(持续)
    else KEY_EVENT_UP
        APP->>HID: ble_hid_data_send(1, &key_msg_up, 2)
        HID->>HOST: 全0报告(bit=0)
    end

流程要点:按键事件先并行触发 LED 反馈与 IR 处理(IR 受"BLE 已连接且非电源键则跳过"约束),随后按事件类型决定 HID 报告的发送组合。单击必须补发全 0 报告,这是 HID 消费类按键的"瞬时触发"语义,否则主机认为按键被持续按住。

应用状态机与蓝牙事件流

flowchart TD
    subgraph sg_APP_LIFE["应用生命周期 (hidrc_state_machine)"]
        CREATE["APP_STA_CREATE"]
        START["APP_STA_START<br/>ACTION_REMOTE_CONTROL → hidrc_app_start"]
        RUN["消息循环 get_msg + app_comm_process_handler"]
        PAUSE["APP_STA_PAUSE"]
        RESUME["APP_STA_RESUME"]
        STOP["APP_STA_STOP"]
        DESTROY["APP_STA_DESTROY"]
    end

    subgraph sg_BT_EVT["蓝牙事件"]
        INIT_OK["BT_STATUS_INIT_OK"]
        CONN["连接/断开事件"]
    end

    CREATE --> START --> RUN
    RUN --> PAUSE --> RESUME --> RUN
    RUN --> STOP --> DESTROY
    INIT_OK -->|"btstack_ble_start_after_init"| RUN
    CONN -->|"bt_comm_ble_status_event_handler"| RUN

蓝牙事件处理拆分为两个回调:hidrc_bt_hci_event_handler(HCI 层事件,统一转交 bt_comm_ble_hci_event_handler)与 hidrc_bt_connction_status_event_handler(连接状态事件,BT_STATUS_INIT_OK 时调用 btstack_ble_start_after_init(0) 真正开始广播,其余转交公共处理):

static int hidrc_bt_connction_status_event_handler(struct bt_event *bt)
{
    log_info("----%s %d", __FUNCTION__, bt->event);

    switch (bt->event) {
    case BT_STATUS_INIT_OK:
        // 蓝牙初始化完成
        log_info("BT_STATUS_INIT_OK\n");
        btstack_ble_start_after_init(0);
        break;
    default:
        bt_comm_ble_status_event_handler(bt);
        break;
    }
    return 0;
}

Source: app_remote_control.c

设计意图:BLE 初始化分为"开始前(配置)→ 开始后(广播)"两个阶段,中间由 BT_STATUS_INIT_OK 事件同步——这保证了协议栈完全就绪后才进入可发现/可连接状态,避免竞态。hidrc_state_machine 中 APP_STA_START 只在 it->action == ACTION_REMOTE_CONTROL 时启动应用,说明该 Demo 由外部 action 触发,可被框架按需拉起。

软关机时序

sequenceDiagram
    participant T as "sys_timer"
    participant PWR as "app_power_mg"
    participant APP as "hidrc_set_soft_poweroff"
    participant BT as "btstack"
    participant HOST as "BLE主机"

    T->>PWR: 定时到期 → POWER_EVENT_POWER_SOFTOFF
    PWR->>APP: app_power_set_soft_poweroff 流程
    APP->>BT: btstack_ble_exit(0)
    alt 已连接
        alt SOFT_MODE
            APP->>PWR: 延时 WAIT_DISCONN_TIME_MS 后软关机(不等断链)
        else SOFT_BY_POWER_MODE
            APP->>PWR: app_power_soft.wait_disconn = 1 (必须等断链)
            HOST-->>BT: 断开连接
            BT-->>PWR: 断链完成 → 执行软关机
        end
    else 未连接
        APP->>PWR: 立即软关机
    end

hidrc_set_soft_poweroff() 是低功耗设计的核心:软关机前先 btstack_ble_exit(0) 关闭协议栈;已连接时按低功耗模式决定"等不等断链"——SOFT_MODE 下用 sys_timeout_add 延时 WAIT_DISCONN_TIME_MS 后直接关机(省电优先),SOFT_BY_POWER_MODE 下置 wait_disconn = 1 由电源模块等待链路断开(可靠性优先)。

板级配置

遥控器示例对应板级目录 apps/demo/hid/board/bd57/,其中 board_aw33n_rc_cfg.h(宏开关)与 board_aw33n_rc_global_build_cfg.h(构建/Flash 布局)配套使用,宏开关包括:

宏说明
TCFG_IR_ENABLE使能红外发射(配套 IR_KEY_IO、IR_WORK_FRQ、IR_WORK_DUTY 配置)
TCFG_LED_ENABLE使能 LED 反馈(LED_KEY_UP、LED_INIT_FLASH)
TCFG_HID_AUTO_SHUTDOWN_TIME无操作自动软关机秒数,0 表示关闭
TCFG_ADKEY_VALUE0/1/3AD 按键对应的键值,用于双击配对、三击关机判断
TCFG_LOWPOWER_PATTERN低功耗模式(SOFT_MODE / SOFT_BY_POWER_MODE)

构建配置(board_aw33n_rc_global_build_cfg.h)中针对遥控器产品形态的关键取舍:

#define CONFIG_DOUBLE_BANK_ENABLE               0       // 单备份结构(无第三方OTA双备份需求)
#define CONFIG_FLASH_SIZE                       FLASH_SIZE_256K
#define CONFIG_VM_LEAST_SIZE                    0x2000  // VM区最小尺寸
#define CONFIG_BTIF_LEN	                        0x1000
#define UPDATE_V2_EN                            1       // 升级功能使能
#define TESTBOX_BT_UPDATE_EN                    1       // 测试盒升级
#define CONFIG_APP_OTA_EN                       0       // 不使能 RCSP(JL-OTA) 升级
#define HAS_USB_EN                              0
#define HAS_NORFS_EN                            0

Source: board_aw33n_rc_global_build_cfg.h

设计意图:遥控器 Flash 通常较小(256K),且无需 USB 与 NORFS;保留测试盒 BT 升级通道便于产线烧录与售后维护,关闭 RCSP OTA 以精简代码体积。若需接入第三方 OTA 协议,需同时打开 CONFIG_DOUBLE_BANK_ENABLE 并按实际 Flash 大小配置 CONFIG_FLASH_SIZE。

API 参考

以下为本示例直接调用的 SDK 接口(签名取自实际调用点,完整声明见对应 SDK 头文件)。

ble_hid_data_send(report_id, data, len)

发送 HID 输入报告(设备→主机方向)。

参数:

  • report_id (uint8_t):报告 ID,示例固定传 1,对应报告描述符中 Report ID (1)。
  • data (uint8_t *):报告数据指针,2 字节消费类位图。
  • len (uint16_t):数据长度,示例传 2。

说明: 按下时传置位值(如 CONSUMER_VOLUME_INC = 0x0001),松开时传 0。

ble_hid_is_connected()

返回当前 BLE HID 链路是否已连接,供 IR 联动策略判断(连接时除电源键外跳过 IR)。

le_hogp_disconnect() / le_hogp_set_pair_allow()

  • le_hogp_disconnect():主动断开当前 HOGP 连接。
  • le_hogp_set_pair_allow():设置设备允许配对(进入可配对状态)。
  • 组合用法:双击键值 1 时先断开再允许配对,实现重新配对。

le_hogp_set_reconnect_adv_cfg(type, timeout_ms)

配置断链回连广播参数。示例:le_hogp_set_reconnect_adv_cfg(ADV_DIRECT_IND_LOW, 5000) —— 使用低占空比定向广播,持续 5000 ms。

le_hogp_set_output_callback(cb)

注册下行通道回调(主机→设备数据),示例回调 hidrc_recv_callback 仅打印收到的数据(ble_hid_data_receive:size=%d + put_buf)。

btstack_ble_start_before_init(cfg, flag) / btstack_ble_start_after_init(flag) / btstack_ble_exit(flag)

  • btstack_ble_start_before_init:加载 BLE 配置(ble_init_cfg_t,含外观、报告映射、HOGP 钩子)并完成初始化前准备。
  • btstack_ble_start_after_init:在 BT_STATUS_INIT_OK 事件后调用,真正启动广播/扫描。
  • btstack_ble_exit(0):关闭 BLE 协议栈(软关机前调用)。

ir_encoder_init(io, freq, duty) / ir_encoder_tx_hx(ch, cmd, is_long) / ir_encoder_repeat_stop()

  • ir_encoder_init:初始化红外发射 IO、载波频率与占空比(示例:IR_KEY_IO、IR_WORK_FRQ、IR_WORK_DUTY)。
  • ir_encoder_tx_hx(0, cmd, is_long):发送 HX 编码红外码,cmd 为操作码,is_long 为是否持续发送(长按重复)。
  • ir_encoder_repeat_stop():停止长按重复发送(KEY_EVENT_UP 时调用)。

sys_timeout_add(arg, func, msec) / sys_timeout_del(timer_id)

  • 添加系统软定时器:sys_timeout_add((void *)POWER_EVENT_POWER_SOFTOFF, (void *)app_power_event_to_user, ms) 实现自动关机;sys_timeout_del(hidrc_auto_shutdown_timer) 取消。

app_power_event_to_user(POWER_EVENT_POWER_SOFTOFF) / app_power_set_soft_poweroff(NULL)

投递软关机事件 / 直接请求软关机。示例在未连接时直接调用后者,已连接时按低功耗模式走延时或等断链路径。

led_operate(LED_KEY_UP | LED_INIT_FLASH)

LED 控制接口,按键反馈与开机闪灯。

app_comm_process_handler(msg) / get_msg(count, msg)

消息循环:get_msg 阻塞获取消息,app_comm_process_handler 分发处理(按键、蓝牙等事件均由框架投递到该循环)。

故障模式、边界情况与并发

按键事件与 HID 发送的竞态

ble_hid_data_send 与 ir_encoder_tx_hx 在按键回调上下文中同步调用,不涉及跨任务共享状态;但单击补发全 0 报告依赖主机在收到置位报告后及时处理——若两次发送间隔过近(< 连接间隔),主机可能合并为单次报告导致按键丢失。量产时若出现丢键,需按连接参数(connection interval)调整补发节奏或使用重复发送。

长按报告缺失的边界

hidrc_hold_table 中值为 0 的键(如上一曲/下一曲)在长按时 key_msg = 0,此时既不发 HID 报告,也不会进入双击/三击分支——即长按无功能键被静默忽略,属预期行为。但若误将需要长按的键配为 0,排查时需先确认两张表。

IR 与 BLE 同时按下

IR 键处理先于 BLE 发送执行;当 BLE 已连接且按键非电源键时 IR 被跳过,因此同一按键只会走一个通道,不会双发。电源键例外(始终 IR),保证电视可被强制关机。

软关机与断链的时序依赖

SOFT_MODE 下软关机不等待链路断开(延时 WAIT_DISCONN_TIME_MS 后直接关),若此时主机仍在收发数据,可能出现收尾数据丢失;SOFT_BY_POWER_MODE 通过 wait_disconn = 1 强制等断链,更可靠但关机延迟更长。两者取舍取决于产品对"关机延迟 vs 数据完整性"的偏好。

自动关机定时器与手动关机的交互

三击软关机(POWER_EVENT_POWER_SOFTOFF)与自动关机定时器共用同一事件,若两者同时触发(如定时器到期瞬间用户三击),hidrc_set_soft_poweroff 会执行两次——由于 btstack_ble_exit 幂等且软关机状态机可重入,通常无害;但如需严格单次,应在 hidrc_auto_shutdown_disable() 中统一取消定时器。

配对失败/回连超时

回连广播使用 ADV_DIRECT_IND_LOW 持续 5000 ms,若主机不在范围内则超时静默。设备保持可发现状态由框架层管理;用户可通过双击键值 1 强制重新进入可配对状态。

性能与运维考量

  • 时钟配置前置:hidrc_app_start 在初始化蓝牙前显式设置 sys/lsb/sfc 时钟(clk_set),并调用 clock_bt_init() 与 bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0) 配置 PLL。若系统时钟与晶振参数不匹配,BLE 射频将无法通过认证,这是联调时最先应检查的项。
  • 报告体积极小:HID 报告仅 2 字节,每次按键产生 ≤2 个通知,BLE 带宽占用可忽略;功耗主要由广播占空比(ADV_DIRECT_IND_LOW)与连接间隔决定。
  • 低功耗关键点:hidrc_is_active 标志在 SOFT_MODE 下置 1,标识"软关机临界点"(禁止系统进入低功耗)——软关机流程完成前系统不允许休眠,避免在蓝牙未完全关闭时掉入深睡。
  • 日志开关:模块使用 LOG_TAG "[HID_RC]",默认开启 ERROR/DEBUG/INFO/CLI;量产可关闭 LOG_DEBUG_ENABLE/LOG_INFO_ENABLE 减小代码与运行开销。
  • 产线升级:TESTBOX_BT_UPDATE_EN = 1 使能测试盒 BT 升级,TCFG_UART_UPDATE_PORT = IO_PORTA_00 需与 isd_config.ini 的 UTRX 匹配;串口升级默认关闭。

扩展点

1. 增加按键功能

修改 hidrc_click_table/hidrc_hold_table(长度需覆盖键值上限),并同步扩展 hidrc_report_map 中的 Usage 与 Report Count。例如增加"语音助手"键:在报告映射中追加 0x09, 0x01, // Usage (Voice Command) 并增大 0x95 的 count,再在表中加入对应消费类码。

2. 更换红外协议/电视品牌

替换 hidrc_ir_cmd_tab 的 cmd 码表(当前匹配海信电视),或改写 hidrc_send_ir_key 使用其它 ir_encoder_* 发送接口(NEC/HX 等编码由 ir_encoder 模块支持情况决定)。IR_POWER_CMD_VALUE 常量用于识别电源键,换码表时需同步更新。

3. 适配不同按键矩阵

按键事件由框架按 TCFG_ADKEY_VALUEx 上报;本示例以固定键值表索引取码。若改用矩阵扫描(GPIO 行列),只需替换按键事件来源,hidrc_app_key_deal_test 的映射逻辑可复用。

4. 定制软关机策略

hidrc_set_soft_poweroff 中的 SOFT_MODE / SOFT_BY_POWER_MODE 分支是低功耗策略扩展点:可在 wait_disconn = 1 路径中追加"保存用户配置到 VM"或"上报关机状态给主机"等收尾动作。

5. 下行数据响应

le_hogp_set_output_callback(hidrc_recv_callback) 目前只打印数据;如需响应主机下发的指令(如电视回传频道信息、固件升级数据),在此回调内扩展协议解析即可。

测试与验证建议

SDK 中未提供该示例的独立单元测试文件(HID 应用依赖硬件外设与协议栈,通常以整机联调为主)。建议的验证矩阵:

验证项方法预期
按键上报连接手机/PC BLE 调试工具查看 HID 报告单击出现置位+清零两帧,长按仅置位帧
IR 兜底断开 BLE 后按键对准海信电视电视响应且无 BLE 帧发出
电源键BLE 连接状态下按电源键电视关机(IR 通道)
自动关机设置 TCFG_HID_AUTO_SHUTDOWN_TIME 后静置定时器到期软关机,日志打印 hidrc_set_soft_poweroff
重新配对双击键值 1断开旧连接并进入可配对广播
回连断开后 5 s 内靠近主机定向广播回连成功

相关链接

  • app_remote_control.c(本示例完整源码)
  • board_aw33n_rc_global_build_cfg.h(遥控器板级构建配置)
  • board_aw33n_rc_cfg.h(遥控器板级宏开关)
  • board_aw33n_rc.c(遥控器板级驱动)
  • app_main.c(HID 应用入口)
  • 相关模块文档:BLE HOGP(ble_hogp)、红外编码器(ir_encoder)、LED 控制(led_control)、电源管理(app_power_mg)
  • 同目录其他 HID 示例:鼠标示例、键盘示例
Prev
鼠标设备示例
Next
HID 蓝牙应用模块