键盘、翻页器与遥控应用
本文档介绍 AW31N BLE SDK 中基于 BLE HID(HOGP)协议的键盘、翻页器与遥控器应用族,涵盖应用选择机制、入口分发逻辑、各应用实现要点、底层按键/红外驱动支撑以及相关配置项。
Purpose and Scope
本页面向 apps/demo/hid 目录下的 HID 外设应用族,重点说明:
- 如何通过
app_config.h中的CONFIG_APP_*宏在键盘(KEYBOARD)、翻页器(KEYPAGE)、遥控器(REMOTE_CONTROL)等应用之间切换; app_main.c入口如何根据宏分发到不同的应用 action;- 翻页器
app_keypage.c与遥控器(hid_rc)的实现要点,以及它们依赖的 BSP 按键驱动(key)与红外编解码(ir)组件; - HID 应用相关的 BLE 协议栈配置(HOGP、GATT、SM)与内存/低功耗配置。
不在本页范围:单模/三模鼠标应用(CONFIG_APP_MOUSE_SINGLE / CONFIG_APP_MOUSE_DUAL / CONFIG_APP_MOUSE_LOW_LATENCY)、自拍器(KEYFOB)与 IDLE 模式属于独立的同类应用,建议由对应的鼠标应用与低功耗/IDLE 页面单独说明;BSP 层 key、ir 组件的逐函数细节亦由各自组件页面覆盖,本页仅从应用使用角度引用。
Overview
AW31N 是一颗支持 BLE 的单芯片方案,SDK 在 apps/demo/hid 下提供了一个演示工程,把最常见的 BLE HID 外设形态——键盘、自拍器、鼠标、翻页器、遥控器、IDLE——统一放在同一个工程中,通过编译期宏“只选 1 个”的方式选择目标应用。
这种设计的意图很明确:HID 外设的差异化主要在于上报内容(HID Report 的用法页不同:键盘用 Generic Desktop/Keyboard 页,翻页器用 Consumer 页的媒体键,遥控器可复用键盘页或自定义)与输入采集方式(按键矩阵/AD 键/IO 键/红外解码),而 BLE 连接、GATT、配对、低功耗等公共部分完全可以复用。因此 SDK 把公共部分下沉为 CONFIG_HOGP_COMMON_ENABLE 使能的公共 HOGP 模块,应用层只需完成“按键/IR 事件 → HID Report 组装 → 上报”这一段逻辑。
app_config.h 中明确要求“app case 选择,只选 1,要配置对应的 board_config.h”,例如遥控器必须搭配 CONFIG_BOARD_AW31A_RC 板级配置——因为遥控器方案在硬件上需要红外发射/接收管脚与对应板级管脚映射,配置宏与板级必须成对出现。
Architecture
下图展示键盘、翻页器、遥控应用在 SDK 中的分层结构与依赖关系(节点名均来自实际源码/配置宏):
flowchart TD
subgraph sg_App["应用层 apps/demo/hid"]
AppMain["app_main.c<br/>入口与 action 分发"]
Kbd["键盘应用<br/>CONFIG_APP_KEYBOARD"]
Keypage["翻页器应用<br/>app_keypage.c"]
RC["遥控器应用<br/>hid_rc"]
end
subgraph sg_Profile["HID 公共模块"]
HOGP["HOGP 公共模块<br/>CONFIG_HOGP_COMMON_ENABLE"]
Report["HID Report 协议"]
end
subgraph sg_BLE["BLE 协议栈"]
GATT["GATT Server<br/>CONFIG_BT_GATT_SERVER_NUM=1"]
SM["SM 安全模块<br/>CONFIG_BT_SM_SUPPORT_ENABLE"]
end
subgraph sg_BSP["BSP 驱动层"]
KeyDrv["key 驱动<br/>key_drv_io/ad/matrix"]
IRDrv["IR 编解码<br/>ir_decoder/ir_encoder"]
end
AppMain -->|"根据 CONFIG_APP_* 分发"| Kbd
AppMain --> Keypage
AppMain --> RC
Kbd --> HOGP
Keypage --> HOGP
RC --> HOGP
HOGP --> Report
Report --> GATT
GATT --> SM
Kbd --> KeyDrv
Keypage --> KeyDrv
RC --> IRDrv
各层职责:
- 应用层(
apps/demo/hid):app_main.c是唯一入口,它根据app_config.h中置 1 的CONFIG_APP_*宏把应用名与 action 绑定(例如翻页器为"keypage"/ACTION_KEYPAGE,遥控器为"hid_rc"/ACTION_REMOTE_CONTROL)。各应用实现位于examples/子目录,如翻页器为examples/keypage/app_keypage.c。 - HID 公共模块:
CONFIG_HOGP_COMMON_ENABLE = 1使能公共 HOGP(HID over GATT Profile),应用只需填充 HID Report,无需重复实现 GATT 服务注册与报告上报。 - BLE 协议栈:
app_config.h中配置了 GATT 从机数量为 1、使能 SM 加密(遥控/键盘需要配对与加密),公共 GATT 模块由CONFIG_BT_GATT_COMMON_ENABLE使能。 - BSP 驱动层:键盘/翻页器依赖
apps/app/bsp/common/key/下的按键驱动(IO 键、AD 键、矩阵键),遥控器方案需要红外收发,依赖apps/app/bsp/common/ir/的ir_decoder.c/ir_encoder.c。
架构设计的关键取舍:把“应用形态”与“输入采集”解耦。同一套按键扫描、去抖、消息机制可服务键盘与翻页器,红外编解码可服务遥控器,而 HID 上报走公共 HOGP。新增一种外设时,只需新增一个 CONFIG_APP_* 宏、一个 examples/xxx/app_xxx.c,并在 app_main.c 增加一个分支。
应用选择机制(app case 开关)
HID 演示工程通过一组互斥的编译期宏决定构建哪种应用。源码位于 apps/demo/hid/include/app_config.h:
//app case 选择,只选1,要配置对应的board_config.h
#define CONFIG_APP_KEYBOARD 1//hid按键 ,default case
#define CONFIG_APP_KEYFOB 0//自拍器,
#define CONFIG_APP_MOUSE_SINGLE 0//单模鼠标(ble) 需搭配CONFIG_BOARD_AW313A_MOUSE_SINGLE板级
#define CONFIG_APP_MOUSE_DUAL 0//三模鼠标(ble&2.4g&usb) 需搭配CONFIG_BOARD_AW313A_MOUSE板级
#define CONFIG_APP_MOUSE_LOW_LATENCY 0//低延时从机,高回报率测试,需搭配CONFIG_BOARD_AW313A_MOUSE板级
#define CONFIG_APP_KEYPAGE 0//翻页器
#define CONFIG_APP_REMOTE_CONTROL 0//遥控器,需搭配CONFIG_BOARD_AW31A_RC板级
#define CONFIG_APP_IDLE 0//IDLE
Source: app_config.h
设计意图:
- 互斥保证:注释明确“只选 1”。因为多个应用会同时编译进镜像并产生重复的符号/资源,SDK 要求开发者把目标应用置 1、其余置 0。默认 case 是键盘(
CONFIG_APP_KEYBOARD 1),保证开箱即用。 - 板级强绑定:鼠标、遥控器宏的注释都标注了必须搭配的板级配置(如遥控器需
CONFIG_BOARD_AW31A_RC)。这些外设在管脚映射、外设资源上与默认键盘板不同,宏与板级必须成对配置,否则驱动初始化会失败或管脚冲突。 - 宏驱动内存分配:
app_config.h后续的#if (CONFIG_APP_MOUSE_DUAL) || (CONFIG_APP_MOUSE_LOW_LATENCY)、#elif(!CONFIG_APP_IDLE)、#else分支会按应用类型调整 BLE 消息池、堆与栈大小——高回报率鼠标需要更大的CONFIG_BT_API_MSG_BUFSIZE/CFG_BT_MSG_BUFSZIE与BT_NK_RAM_SIZE,IDLE 模式则把蓝牙相关内存全部归零。键盘/翻页器/遥控器走#elif(!CONFIG_APP_IDLE)分支,使用通用的“有 BLE 但不高回报率”配置。
入口分发:app_main.c
所有 HID 应用共享同一个入口 app_main.c。工程初始化时,它把应用名与 action 绑定,供上层任务调度/事件循环识别当前运行的应用:
#elif(CONFIG_APP_KEYPAGE)
it->name = "keypage";
it->action = ACTION_KEYPAGE;
#elif(CONFIG_APP_REMOTE_CONTROL)
it->name = "hid_rc";
it->action = ACTION_REMOTE_CONTROL;
Source: app_main.c
代码采用 #if/#elif 链按 CONFIG_APP_* 依次匹配(键盘为默认分支,翻页器、遥控器紧随其后),与 app_config.h 的宏一一对应。it 是应用信息结构体,name 用于日志/调试标识,action 用于驱动上层消息路由——例如翻页器收到按键事件后按 ACTION_KEYPAGE 走翻页上报路径,遥控器按 ACTION_REMOTE_CONTROL 走 IR/按键上报路径。这种“一个入口 + 编译期分发”的模式避免了运行时多态开销,适合资源受限的嵌入式场景。
翻页器应用(app_keypage.c)
翻页器的实现在 apps/demo/hid/examples/keypage/app_keypage.c,文件开头用条件编译包裹,确保只有在 CONFIG_APP_KEYPAGE 置 1 时才参与编译:
#include "app_keypage.h"
#if(CONFIG_APP_KEYPAGE)
#define LOG_TAG_CONST KEYPAGE
#define LOG_TAG "[KEYPAGE]"
Source: app_keypage.c
工作机理:翻页器本质是一个“少键位 HID 键盘”——通常只有上一页/下一页两个按键,通过 HID Consumer 页(Usage 0x00B6 / 0x00B7,即 AC Previous / AC Next)或键盘页的 PageUp/PageDown 上报。应用复用 BSP 按键驱动采集 IO 键状态,去抖后映射为对应的 HID Usage,再经公共 HOGP 模块以 HID Report 形式发送给已配对主机(如演示文稿翻页场景中的电脑/手机)。
日志方面,app_config.h 之外,apps/demo/hid/config/log_config.c 为 KEYPAGE 单独登记了日志标签(log_tag_const_*_KEYPAGE),使能 v/i/d/w/e 各级别的条件打印,便于在键盘/翻页器/遥控器共存调试时按模块过滤日志。
遥控器应用(hid_rc)
遥控器应用在 app_main.c 中的标识为 "hid_rc"、action 为 ACTION_REMOTE_CONTROL,且必须搭配 CONFIG_BOARD_AW31A_RC 板级配置。遥控器方案的输入来源有两类:
- 按键输入:复用 BSP 按键驱动(
apps/app/bsp/common/key/下的key_drv_io.c/key_drv_ad.c/key_drv_matrix.c); - 红外收发:作为遥控器,方案需要红外发射(学习/转发)与红外接收(被其他遥控器控制)能力,依赖
apps/app/bsp/common/ir/下的ir_decoder.c与ir_encoder.c。
驱动配置 apps/demo/hid/config/lib_driver_config.c 中为遥控器应用做了专门的硬件资源使能:
#elif CONFIG_APP_REMOTE_CONTROL
const u8 lib_gptimer_timer_mode_en = 1; //gptimer timer功能使能
Source: lib_driver_config.c
lib_gptimer_timer_mode_en = 1 表明遥控器方案需要通用定时器(GPTimer)的 timer 功能——红外解码通常依赖高精度定时测量载波脉宽/脉冲间隔(NEC/RC 等协议的电平持续时间),这正是 GPTimer 计时能力的用武之地。这一行与默认键盘/翻页器的驱动配置分支区分开,体现“按应用裁剪外设资源”的 SDK 设计原则:不需要的外设驱动与资源不编译/不初始化,从而节省 RAM/ROM 并降低功耗。
遥控器上报到主机的同样是 HID Report(通常映射为键盘多媒体键或自定义 Consumer 键值),连接、配对、加密与键盘应用共用同一套 BLE 配置。
核心流程:从按键/红外到 HID 上报
以键盘/翻页器为例,一次按键上报的完整数据流如下:
sequenceDiagram
participant U as 用户按键/遥控按键
participant K as BSP key 驱动<br/>(key_drv_io/ad/matrix)
participant A as 应用层<br/>(app_main / app_keypage)
participant H as HOGP 公共模块
participant G as GATT Server / SM
participant P as 已配对主机(PC/手机)
U->>K: 按下/释放
activate K
K->>K: 扫描、去抖、判定按键事件
K->>A: 按键消息(按下/长按/释放)
deactivate K
activate A
A->>A: 按 action 映射为 HID Usage<br/>(KEYPAGE/REMOTE_CONTROL/KEYBOARD)
A->>H: 组装 HID Report
deactivate A
activate H
H->>G: 经 GATT Characteristic 上报
G->>G: 加密连接时 SM 加密通道
G->>P: BLE 空中上报
deactivate H
P-->>P: 主机解析 HID Report 并执行动作(翻页/媒体键)
步骤说明:
- 采集:BSP 按键驱动周期性扫描 IO/AD/矩阵键位,内部完成去抖与状态判定(按下、长按、释放),生成按键消息投递给应用层;遥控器方案的 IR 解码由 GPTimer 计时辅助
ir_decoder.c完成。 - 映射:应用层按
app_main.c绑定的 action(ACTION_KEYBOARD/ACTION_KEYPAGE/ACTION_REMOTE_CONTROL)把物理键位映射为 HID Usage 值(翻页键 → Consumer 页 AC Previous/Next,键盘键 → Keyboard 页键值)。 - 上报:经
CONFIG_HOGP_COMMON_ENABLE使能的公共 HOGP 模块组装 HID Report,写入 GATT 的 HID Report Characteristic;若连接已加密(CONFIG_BT_SM_SUPPORT_ENABLE = 1),数据在加密通道上传输。 - 主机侧:主机(PC/手机)解析 HID Report,执行翻页、媒体控制或文本输入等动作。
配置选项
以下配置集中在 apps/demo/hid/include/app_config.h,是构建键盘/翻页器/遥控应用的关键开关:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CONFIG_APP_KEYBOARD | 宏(0/1) | 1 | HID 键盘应用,默认 case |
CONFIG_APP_KEYPAGE | 宏(0/1) | 0 | 翻页器应用 |
CONFIG_APP_REMOTE_CONTROL | 宏(0/1) | 0 | 遥控器应用,需搭配 CONFIG_BOARD_AW31A_RC 板级 |
CONFIG_APP_KEYFOB | 宏(0/1) | 0 | 自拍器应用(本页不展开) |
CONFIG_APP_MOUSE_SINGLE/DUAL/LOW_LATENCY | 宏(0/1) | 0 | 鼠标应用(本页不展开) |
CONFIG_APP_IDLE | 宏(0/1) | 0 | IDLE 模式(本页不展开) |
CONFIG_HOGP_COMMON_ENABLE | 宏(0/1) | 1 | 使能公共 HOGP 模块,HID 上报的公共基础 |
CONFIG_BT_GATT_COMMON_ENABLE | 宏(0/1) | 1 | 使能公共 GATT 模块 |
CONFIG_BT_SM_SUPPORT_ENABLE | 宏(0/1) | 1 | 使能 BLE 加密配对(鼠标低延时应用为 0) |
CONFIG_BT_GATT_SERVER_NUM | 宏 | 1 | GATT 从机(server)数量 |
CONFIG_BT_GATT_CLIENT_NUM | 宏 | 0 | GATT 主机(client)数量,HID 应用不支持 |
CONFIG_BT_GATT_CONNECTION_NUM | 宏 | 1 | 连接数 = server + client |
CONFIG_BLE_CONNECT_SLOT | 宏(0/1) | 0 | BLE 高回报率私有协议开关(仅鼠标应用为 1) |
TCFG_HID_AUTO_SHUTDOWN_TIME | 秒 | 0 | HID 无操作自动关机时间,0 表示不自动关机 |
CONFIG_SET_1M_PHY / CONFIG_SET_2M_PHY | 宏 | 1 / 2 | BLE PHY 速率配置 |
lib_gptimer_timer_mode_en | u8 | 0(默认分支) | 遥控器应用置 1,使能 GPTimer timer 功能(IR 解码计时) |
前 8 项来源:app_config.h;BLE 相关项来源:app_config.h;GPTimer 项来源:lib_driver_config.c
注意事项:
CONFIG_APP_*必须且只能有一个置 1,且要同步选择匹配的board_config.h板级配置;- 修改
CONFIG_BT_*_MSG_BUFSIZE、SYS_HEAP_SIZE、BT_NK_RAM_SIZE等内存参数前需谨慎——注释明确“SDK 应用内存分配,谨慎修改”,键盘/翻页器/遥控器应用使用非鼠标、非 IDLE 分支的通用内存配置; - 使能
CONFIG_BLE_HIGH_SPEED(DLE+2M)时,若同时使能低功耗(TCFG_LOWPOWER_LOWPOWER_SEL),编译期#error "Please close low power if enable high speed"会直接报错,防止无效组合。
故障模式、边界情况与并发
- 多应用宏同时置 1:
app_config.h要求“只选 1”。若同时打开键盘与翻页器,app_main.c的#if/#elif链只会命中第一个匹配分支,其余应用代码虽可编译但不会进入 action 路由,且可能因重复符号/资源冲突导致链接错误或运行异常。排查时先确认 8 个CONFIG_APP_*宏的互斥性。 - 板级配置不匹配:遥控器宏要求
CONFIG_BOARD_AW31A_RC板级,鼠标要求 AW313A 板级。若只开宏不换板级,按键/IR 的管脚映射与外设时钟配置会错位,表现为按键无响应或 IR 无法解码——这类问题在硬件上极难排查,因此 SDK 在注释中反复强调成对配置。 - 编译期约束冲突:
CONFIG_BLE_HIGH_SPEED与低功耗同开时,预处理#error直接终止编译。这是 SDK 主动把“不可用组合”提前到编译期暴露的设计,避免运行期出现不可预期的连接异常。 - IR 解码时序边界:遥控器依赖 GPTimer 计时测量红外脉宽。NEC 等协议的载波周期在微秒量级,若系统低功耗模式频繁挂起计时器或中断响应延迟过大,解码会出现错帧。工程中遥控器应用单独使能
lib_gptimer_timer_mode_en,正是为了保证计时精度;后续扩展 IR 协议时应关注定时器中断优先级与低功耗唤醒延迟。 - 上报并发/丢包:HID 键盘类应用通常需要“按下+释放”成对上报,若 BLE 连接事件间隔内上报队列积压(如连击),公共 HOGP 模块按 GATT 写入节奏排队发送;低功耗休眠可能推迟上报,主机侧表现为偶发丢键。翻页器这类低速场景不受影响,但高频率按键场景需评估
CONFIG_BLE_CONNECT_SLOT与连接间隔配置(鼠标类才建议开高回报率)。 - 自动关机边界:
TCFG_HID_AUTO_SHUTDOWN_TIME以秒为单位,置 0 表示永不自动关机;若设为 N 分钟,则从最后一次 HID 上报起计时,超时无操作进入关机流程——注意“最后一次上报”以实际发包为准,按键长按持续上报会重置计时。
性能与运维考量
- 内存裁剪:
app_config.h顶部按应用类型划分三档内存配置(高回报率鼠标 / 普通 BLE 应用 / IDLE),键盘、翻页器、遥控器共用普通档:CONFIG_BT_API_MSG_BUFSIZE 0xa0、CONFIG_HOST_MSG_BUFSIZE 0x100、CONFIG_CTRL_MSG_BUFSIZE 0x100、BT_NK_RAM_SIZE 0x460+CFG_BT_MSG_BUFSZIE、BT_NV_RAM_SIZE 0xDC0。这些参数决定 BLE 协议栈可容纳的命令/事件消息深度,直接影响高负载时的吞吐;非必要不建议改动。 - 日志开关:
CONFIG_DEBUG_ENABLE与CONFIG_SDK_DEBUG_LOG控制总打印与堆/栈/内存统计输出;发布版本可用CONFIG_RELEASE_ENABLE把LIB_DEBUG置 0 裁剪调试代码。log_config.c中 KEYPAGE 的log_tag_const_*开关可单独裁剪翻页器日志,遥控器(hid_rc)日志同样按 tag 控制,便于线上问题定位时只保留相关模块日志。 - 低功耗:键盘/翻页器/遥控器默认走
TCFG_LOWPOWER_LOWPOWER_SEL低功耗路径(CONFIG_BLE_HIGH_SPEED为 0 时无冲突);TCFG_HID_AUTO_SHUTDOWN_TIME配合无操作自动关机可进一步延长电池寿命。IR 解码期间的低功耗策略需按遥控器方案单独验证。 - PHY 配置:
CONFIG_SET_1M_PHY 1、CONFIG_SET_2M_PHY 2说明连接建立后会按 1M/2M PHY 协商,2M 可降低空中时间、利于低功耗;高回报率需求下可结合 DLE 评估。
扩展点
- 新增应用形态:在
app_config.h增加CONFIG_APP_XXX宏,在apps/demo/hid/examples/下新建xxx/app_xxx.c,并在app_main.c的#elif链中注册name与action,最后在board_config.h配好板级。公共 HOGP 与 BLE 配置无需改动——这是该应用族最重要的扩展路径。 - 自定义 HID Report:键盘/翻页器/遥控器的差异主要在 Report Map 与 Usage 映射。改报告内容时,同步修改应用层 Usage 映射与 HOGP 模块中的 Report Map 描述符,保证主机解析与上报一致。
- 遥控器 IR 协议扩展:
ir_decoder.c/ir_encoder.c支持协议层扩展(如增加空调/电视厂商协议),在 BSP 层完成脉宽解析后,把解码出的键值送入应用层统一走 HID 上报。 - 按键拓扑扩展:键盘应用支持
key_drv_io/key_drv_ad/key_drv_matrix三种采集方式,新增键位矩阵或 AD 键时只需改板级键表,应用层映射逻辑不变。
相关链接
- apps/demo/hid/include/app_config.h — 应用 case 选择与全部 HID 相关配置
- apps/demo/hid/app_main.c — 入口 action 分发
- apps/demo/hid/examples/keypage/app_keypage.c — 翻页器实现
- apps/demo/hid/config/lib_driver_config.c — 遥控器 GPTimer 驱动配置
- apps/demo/hid/config/log_config.c — KEYPAGE 日志标签开关
- BSP 按键驱动(键盘/翻页器输入):
apps/app/bsp/common/key/key_drv_io.c、key_drv_ad.c、key_drv_matrix.c - BSP 红外编解码(遥控器输入):
apps/app/bsp/common/ir/ir_decoder.c、ir_encoder.c - 鼠标应用(单模/三模/低延时)与 IDLE/低功耗主题请参见对应独立页面