# 单线UART矩阵键盘驱动 **Repository Path**: bitcode-tech/c_uart_keyboard ## Basic Information - **Project Name**: 单线UART矩阵键盘驱动 - **Description**: 使用UART单线接口的矩阵键盘驱动,支持按键按下、释放、组合键、长按键以及无键盘活动的检测。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-04 - **Last Updated**: 2026-06-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # UART 单线矩阵键盘驱动 这是一个轻量级 C 语言库,适用于 BC6xxx 和 BC759x 系列 UART 单线键盘接口芯片。BC6xxx 系列仅提供键盘接口功能,BC759x 系列则集成了 LED 显示驱动。支持的型号包括: - **[BC6301](docs/bc6301.pdf)** (30键) - **[BC6561](docs/bc6561.pdf)** (56键) - **[BC6088A](docs/bc6088.pdf)** (88键) - **[BC7595](docs/bc7595.pdf)** (48LED+48键) - **[BC7591](docs/bc7591.pdf)** (256LED+96键) 本驱动可将芯片UART输出的原始键码转换为应用程序易于使用的按键事件,支持普通按键按下和释放检测、组合键、长按键以及无按键活动检测。 典型应用电路如下。所有支持的芯片都使用相同的接口和协议,因此在扩大或缩小键盘矩阵规模时,只需要进行很少的软件修改。 ![](img/bc6301_typical.png) --- ## 功能特点 - 标准 C 语言实现 - 兼容 C89 及后续版本的 C 编译器 - 适用于 MCU、嵌入式 Linux、PC 应用以及其他 C 语言环境 - 内存占用非常小 - 简单的 UART 事件输入接口 - 单独按键按下检测 - 可选的按键释放检测 - 支持任意组合键 - 支持长按键 - 可选的回调模式,适用于事件驱动型应用 - 支持无键盘活动检测 - 用户代码量很少 --- ## 工作原理 每当键盘矩阵状态发生变化时,芯片都会输出一个字节,每个接收到的字节表示一个独立按键开关的状态变化,其数值为按键编号。 | 数值范围 | 含义 | | --------------- | ----------------- | | `0x00` - `0x7F` | 按键按下事件,数值为按键编号。 | | `0x80` - `0xFF` | 按键释放事件。最高位为释放标志位。 | 例如: - `0x03` 表示按键 3 被按下。 - `0x83` 表示按键 3 被释放,因为 `0x83 = 0x80 | 0x03`。 **对于简单应用,本库并不是必需的。用户可以直接根据接收到的键值执行对应操作即可。** 本库提供了**组合键和长按检测等高级功能**,使应用程序可以像处理普通单键一样处理复杂的键盘事件。 --- ## 辅助软件 随库提供了辅助软件,将单线UART矩阵键盘电路通过USB-串口连接电脑后,可在电脑上实时看到键盘工作状态。 ![Screenshot-bc6561cn](img/Screenshot-bc6561cn.png) ## 典型工作流程 典型应用通常按以下三个步骤使用本库: 1. 当接收到一个 UART 字节时,调用 `update_key_status()`。 2. 在主循环中调用 `is_key_changed()`,检查是否有新的按键事件。 3. 调用 `get_key_value()` 读取按键值,并清除新事件标志。 --- ## 文件 本驱动包中的核心文件如下: ```text key_scan.c 驱动实现文件 key_scan.h 驱动头文件 ``` 请将 `key_scan.c` 和 `key_scan.h` 一起加入你的项目。 --- ## 快速开始 完整用户手册在[这里(PDF)](docs/UART单线键盘接口驱动库.pdf)。 ```c #include "key_scan.h" int main(void) { while (1) { /* 你的主应用任务 */ do_something(); /* 查询键盘状态 */ if (is_key_changed()) { unsigned char key_value = get_key_value(); switch (key_value) { case 3: /* 按键 3 被按下 */ do_key3_job(); break; case 24: /* 按键 24 被按下 */ do_key24_job(); break; default: break; } } } } void UART_ISR(void) { if (RI) { unsigned char rx_data = RxData; update_key_status(rx_data); } } ``` 默认情况下,本库只报告按键按下事件。除非启用释放检测,否则按键释放事件会被忽略。 --- ## 启用按键释放检测 ```c #include "key_scan.h" int main(void) { set_detect_mode(1); /* 1 = 同时检测按键按下和按键释放 */ while (1) { if (is_key_changed()) { unsigned char key_value = get_key_value(); switch (key_value) { case 3: /* 按键 3 被按下 */ do_key3_press_job(); break; case 0x83: /* 按键 3 被释放:0x80 | 3 */ do_key3_release_job(); break; default: break; } } } } ``` --- ## 长按键示例 长按检测基于按键保持有效期间 `long_press_tick()` 被调用的次数。 ```c #include "key_scan.h" const unsigned char lp1[] = {5, 120}; /* 按键 5 长按 -> 报告 120 */ const unsigned char lp2[] = {20, 121}; /* 按键 20 长按 -> 报告 121 */ const unsigned char* LPDef[] = {lp1, lp2}; int main(void) { set_longpress_count(60); /* 如果每 50 ms 调用一次 long_press_tick(),则为 3 秒 */ def_longpress_key(LPDef, 2); while (1) { if (is_key_changed()) { unsigned char key_value = get_key_value(); switch (key_value) { case 120: /* 按键 5 长按 */ do_key5_longpress_job(); break; case 121: /* 按键 20 长按 */ do_key20_longpress_job(); break; default: break; } } } } void TIMER_ISR(void) { /* 以固定间隔调用,例如每 50 ms 调用一次 */ long_press_tick(); } ``` --- ## 组合键示例 用户可以定义任意按键组合,并为该组合分配一个特殊按键值。之后,该组合键就可以像普通单个按键一样处理。组合键使用如下格式的数组定义: ```c {key_count, defined_value, key1, key2, ...} ``` 示例: ```c #include "key_scan.h" const unsigned char cb1[] = {2, 122, 0, 7}; /* 按键 0 + 按键 7 -> 报告 122 */ const unsigned char cb2[] = {3, 123, 11, 15, 20}; /* 按键 11 + 按键 15 + 按键 20 -> 报告 123 */ const unsigned char* CBDef[] = {cb1, cb2}; unsigned char CBMap[2]; int main(void) { def_combined_key(CBDef, CBMap, 2); while (1) { if (is_key_changed()) { unsigned char key_value = get_key_value(); switch (key_value) { case 122: /* 按键 0 + 按键 7 组合 */ do_combination_1_job(); break; case 123: /* 按键 11 + 按键 15 + 按键 20 组合 */ do_combination_2_job(); break; default: break; } } } } ``` 每个组合键都需要在映射数组中占用 1 字节 RAM。 --- ## 检测无键盘活动 可以使用按键值为 `0xFF` 的特殊长按定义来检测键盘无活动状态。因此,当用户代码收到值为 `0xFF` 的按键事件时,表示键盘状态已经有一段时间没有发生变化。 ```c #include "key_scan.h" const unsigned char lp1[] = {5, 120}; const unsigned char lp2[] = {20, 121}; const unsigned char no_key[] = {255, 255}; const unsigned char* LPDef[] = {lp1, lp2, no_key}; unsigned char no_key_time = 0; int main(void) { set_longpress_count(60); def_longpress_key(LPDef, 3); while (1) { if (is_key_changed()) { unsigned char key_value = get_key_value(); if (key_value == 255) { no_key_time++; if (no_key_time >= 10) { sleep(); } } else { no_key_time = 0; } } } } ``` --- ## 回调模式 当检测到有效键盘事件时,本库可以自动调用用户函数。 ```c #include "key_scan.h" void keyboard_callback(unsigned char key_value) { switch (key_value) { case 3: do_key3_job(); break; default: break; } } int main(void) { set_callback(keyboard_callback); while (1) { do_something(); } } ``` 注意:如果 `update_key_status()` 在 UART 中断中调用,回调函数也会在该中断上下文中执行。请保持回调函数简短,以免增加中断延迟。 --- ## API 参考 ### `void set_detect_mode(uint8_t Mode)` 设置是否报告按键释放事件。 | Mode | 说明 | | ---- | ----------------- | | `0` | 只报告按键按下事件。这是默认模式。 | | `1` | 同时报告按键按下和按键释放事件。 | ### `void set_longpress_count(uint16_t CountLimit)` 设置长按阈值。实际长按时间为: ```text 长按时间 = CountLimit x long_press_tick() 的调用间隔 ``` 默认值:`2000`。 ### `void set_callback(void (*pCallbackFunc)(uint8_t))` 设置键盘事件回调函数。传入 `NULL` 可禁用回调模式。 ### `void update_key_status(uint8_t RxData)` 将接收到的 UART 字节传递给驱动。该函数通常在 UART 接收中断中调用。 ### `void long_press_tick(void)` 递增内部长按计时器。请以固定间隔调用该函数,通常在定时器中断中调用。 ### `uint8_t is_key_changed(void)` 当有新的按键事件可用时,返回非零值。 ### `uint8_t get_key_value(void)` 返回最新按键值,并清除新事件标志。 ### `void def_combined_key(const uint8_t** pCBKeyList, uint8_t* pCBKeyMap, uint8_t CBKeyCount)` 定义用户组合键。 - `pCBKeyList`:指向组合键定义数组的指针数组 - `pCBKeyMap`:用于跟踪组合键状态的 RAM 数组 - `CBKeyCount`:组合键数量 组合键定义格式: ```c {count, defined_value, key1, key2, ...} ``` ### `void def_longpress_key(const uint8_t** pLPKeyList, uint8_t LPKeyCount)` 定义用户长按键。 长按键定义格式: ```c {original_key_value, defined_longpress_value} ``` 使用 `original_key_value = 0xFF` 可检测长时间无键盘活动。 --- ## 集成说明 - 请根据芯片数据手册,将芯片的 UART 输出连接到主机 MCU 的 UART 接收输入。 - 对每个接收到的 UART 字节调用 `update_key_status()`。 - 使用未被占用的按键值作为自定义组合键或长按事件值。 - 如果未启用释放检测,按键释放事件不会报告给应用程序。 - 如果启用了回调模式,`is_key_changed()` 通常不会报告新的按键,因为事件已被回调函数消费。 - 请保持中断服务程序简短,尤其是在使用回调模式时。 --- ## 支持的应用场景 本库适用于: - MCU 键盘输入接口 - Arduino 风格的嵌入式应用 - 工业控制面板 - IoT 设备输入面板 - 智能家居控制设备 - UART 键盘模块 - 基于 BC759x 芯片的七段数码管显示与键盘接口模块