feat(kbd): 添加CAF按钮模块支持

- 在CMakeLists.txt中添加button_map_module.c源文件和头文件目录
- 创建inc/buttons_def.h定义按钮矩阵引脚配置
- 配置prj.conf启用CAF按钮相关功能和参数
- 实现src/modules/button_map_module.c按钮映射逻辑
- 支持6x4键盘矩阵的按键事件处理和Linux输入键码转换
This commit is contained in:
2026-03-10 16:09:33 +08:00
parent cd3400a9ba
commit 3d9ce9168f
4 changed files with 114 additions and 1 deletions

View File

@@ -3,4 +3,9 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(new_kbd) project(new_kbd)
target_sources(app PRIVATE src/main.c) zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
target_sources(app PRIVATE
src/main.c
src/modules/button_map_module.c
)

34
inc/buttons_def.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* CAF buttons 矩阵引脚定义
*
* 设计说明:
* - 本文件被 CAF buttons 模块通过 CONFIG_CAF_BUTTONS_DEF_PATH 直接包含;
* - 行列引脚顺序必须与板级 DTS 中 my_keyboard 的 row-gpios/col-gpios 保持一致;
* - key_id 的行列编号完全基于这里的数组下标,不依赖 input-keymap 节点。
*/
#include <caf/gpio_pins.h>
/*
* 该符号用于保证配置文件只被链接一次:
* 若被重复包含到多个编译单元,会在链接阶段报重复定义,避免静默错配。
*/
const struct {} buttons_def_include_once;
/* 列引脚:对应 atguigu_mini_keyboard.dts 中 my_keyboard/col-gpios 顺序。 */
static const struct gpio_pin col[] = {
{ .port = 0, .pin = 5 },
{ .port = 0, .pin = 6 },
{ .port = 0, .pin = 26 },
{ .port = 0, .pin = 30 },
};
/* 行引脚:对应 atguigu_mini_keyboard.dts 中 my_keyboard/row-gpios 顺序。 */
static const struct gpio_pin row[] = {
{ .port = 0, .pin = 15 },
{ .port = 0, .pin = 7 },
{ .port = 0, .pin = 12 },
{ .port = 0, .pin = 4 },
{ .port = 1, .pin = 9 },
{ .port = 0, .pin = 8 },
};

View File

@@ -12,3 +12,8 @@ CONFIG_CAF_POWER_MANAGER=y
CONFIG_CAF_POWER_MANAGER_TIMEOUT=20 CONFIG_CAF_POWER_MANAGER_TIMEOUT=20
CONFIG_CAF_POWER_MANAGER_ERROR_TIMEOUT=10 CONFIG_CAF_POWER_MANAGER_ERROR_TIMEOUT=10
CONFIG_REBOOT=y CONFIG_REBOOT=y
CONFIG_CAF_BUTTONS=y
CONFIG_CAF_BUTTONS_DEF_PATH="buttons_def.h"
CONFIG_CAF_BUTTONS_SCAN_INTERVAL=5
CONFIG_CAF_BUTTONS_DEBOUNCE_INTERVAL=10

View File

@@ -0,0 +1,69 @@
#include <app_event_manager.h>
#define MODULE button_map
#include <caf/events/module_state_event.h>
#include <caf/events/button_event.h>
#include <caf/key_id.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(MODULE);
/*
* keymap[row][col] 直接对齐板级 DTS 里的 MATRIX_KEY(row, col, key) 定义。
* 值为 Linux input key code-1 表示该矩阵位置未映射功能键。
*/
static const int16_t keymap[6][4] = {
/* row 0 */ { -1, -1, -1, INPUT_KEY_MUTE },
/* row 1 */ { INPUT_KEY_NUMLOCK, INPUT_KEY_KPSLASH, INPUT_KEY_KPASTERISK, INPUT_KEY_KPMINUS },
/* row 2 */ { INPUT_KEY_KP7, INPUT_KEY_KP8, INPUT_KEY_KP9, -1 },
/* row 3 */ { INPUT_KEY_KP4, INPUT_KEY_KP5, INPUT_KEY_KP6, INPUT_KEY_KPPLUS },
/* row 4 */ { INPUT_KEY_KP1, INPUT_KEY_KP2, INPUT_KEY_KP3, -1 },
/* row 5 */ { INPUT_KEY_KP0, INPUT_KEY_KPDOT, -1, INPUT_KEY_KPENTER },
};
static bool app_event_handler(const struct app_event_header *aeh)
{
if (is_button_event(aeh)) {
const struct button_event *event = cast_button_event(aeh);
uint8_t row = KEY_ROW(event->key_id);
uint8_t col = KEY_COL(event->key_id);
/*
* 防御性检查:若行列越界,说明 buttons_def 与实际扫描结果不一致,
* 记录错误以便尽快发现硬件矩阵定义或固件配置问题。
*/
if ((row >= ARRAY_SIZE(keymap)) || (col >= ARRAY_SIZE(keymap[0]))) {
LOG_ERR("Unknown key_id=0x%04x (row=%u, col=%u)", event->key_id, row, col);
return false;
}
int16_t code = keymap[row][col];
if (code < 0) {
LOG_INF("Button %s row=%u col=%u unmapped", event->pressed ? "down" : "up", row, col);
} else {
LOG_INF("Button %s row=%u col=%u keycode=%d", event->pressed ? "down" : "up", row, col, code);
}
return false;
}
if (is_module_state_event(aeh)) {
const struct module_state_event *event = cast_module_state_event(aeh);
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
module_set_state(MODULE_STATE_READY);
}
return false;
}
/* 未处理但已订阅的事件类型不应进入这里。 */
__ASSERT_NO_MSG(false);
return false;
}
APP_EVENT_LISTENER(MODULE, app_event_handler);
APP_EVENT_SUBSCRIBE(MODULE, button_event);
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);