支持的芯片
Ameba SoC |
RTL8721Dx |
RTL8720E |
RTL8726E |
RTL8713E |
RTL8730E |
RTL8721F |
---|---|---|---|---|---|---|
支持状态 |
Y |
N |
N |
N |
N |
N |
概述
Key-Scan 作为一款键盘扫描设备,其行列数可自由配置,最多支持 8 x 8 的键盘矩阵配置。
Key-Scan 支持以下功能:
支持多键检测,最多可同时按下 6 个按键
支持两种工作模式:事件触发模式和常规扫描模式
支持按键卡滞检测
支持低功耗模式及唤醒功能
系统框图
Key-Scan 的框图如下所示:
Key-Scan 主要包含 6 个功能模块:
中断控制:控制和管理中断
寄存器及 FIFO:配置 Key-Scan 参数和 FIFO
时钟模块:131KHz 时钟用于检测行键卡滞的情况
键盘控制:扫描控制、唤醒控制、按键输入/输出控制
GPIO 矩阵:16 个 GPIO 实现 8x8 阵列
键盘矩阵
Key-Scan 的行列可配置,支持的最大列数或行数均为 8。
8x8 键盘矩阵配置
按键被按下后,完整的扫描过程如下:
初始状态下,所有列输出低电平,所有行设置为内部上拉输入。
当有一个或多个按键按下(列与行之间短路)时,被按下按键所在行输入电平由高到低,此时会触发内部状态机启动进行键盘扫描,以确定被按下按键所在的行列。
状态机先将第一列设为输出低电平,其他列设为高阻态,然后扫描所有行来判断哪些按键被按下;接着将第二列设为输出低电平,将所有其他列置于高阻态;重复该过程,直到扫描完最后一列。
经过两次全键盘扫描,最终确认哪些按键被按下。
当所有按键被释放后,Key-Scan 仍会进行两轮全键盘扫描。当确认没有按键被按下后,结束扫描,停止状态机。
下图展示了 2 x 2 键盘按下按键后的扫描时序示意图。
键盘扫描时序
键盘扫描过程中有三个计时器可配置:
消抖计时:两次相邻的全键盘扫描组成一次完整的 full scan,两次全键盘扫描之间都有一次消抖计时。而第一次全键盘扫描之前有一次额外的消抖计时。
扫描间隔计时:两次 full scan 之间需要等待扫描间隔计时器计时结束。
所有按键释放计时:当所有按键被释放,Key-Scan 仍会有一次 full scan(两轮全键盘扫描),等扫描结束后确认无按键按下,释放计时器开始计时。等计时结束,状态机才会停止。
工作模式
Key-Scan 包含两种工作模式:事件触发模式和常规扫描模式。
工作模式 |
描述 |
---|---|
事件触发模式 |
每次按键按下和松开操作,按键按下或松开事件仅在FIFO中仅记录一次 |
常规扫描模式 |
任何按键按下事件都会记录在 FIFO 中(仅记录按键按下事件),直到按键松开 |
下图展示了在按键按下和松开过程中,事件触发模式和常规扫描模式下 FIFO 的差异。
通常情况下,事件触发模式较为常用。该模式下,按键无须连续扫描,仅在按键状态发生改变时扫描键盘。
FIFO 机制
Key-Scan 的 FIFO 深度为 16,宽度为 12 位。其结构如下所示:
位 |
功能 |
参数描述 |
---|---|---|
[8] |
事件 |
|
[7:4] |
行索引 |
|
[3:0] |
列索引 |
|
按键卡滞
在实际使用过程中可能会出现按键卡滞,如果按键未被及时松开,Key-Scan 状态机将持续进行扫描,无法进入 ILDE 状态。CPU 也将保持活动状态持续进行键盘扫描,无法进入低功耗模式,进而产生高功耗。
屏蔽卡滞按键所在行 :为解决此问题,Key-Scan 支持自动检测按键卡滞的功能。启用该功能后,若按键卡滞时间超过设定的阈值,该按键将被视为卡滞按键。通过读取按键卡滞状态寄存器获取卡滞的按键,并设置卡滞按键所在行的默认状态,Key-Scan 在扫描到
该卡滞按键所在行时,会认为没有按键被按下,从而顺利进入 IDLE 状态。
重置卡滞按键所在行 :按键卡滞后,有两种方法可以重置卡滞按键所在行的状态。
一是按下其他非卡滞按键所在行的按键,将 Key-Scan 状态机唤醒,重置卡滞状态寄存器,以唤醒 Key-Scan 的扫描电路;
二是松开卡滞按键,Key-Scan 检测到默认状态寄存器和卡滞状态寄存器的值不匹配,唤醒 Key-Scan 的扫描检测电路。
用法
正常工作模式
使用 Key-Scan 的事件触发模式或常规扫描模式,需执行以下步骤:
配置 Key-Scan 的引脚复用功能。
将列引脚设置为无上下拉,并配置列引脚复用功能。
PAD_PullCtrl(pad_colx, GPIO_PuPd_NOPULL); Pinmux_Config(pad_colx, PINMUX_FUNCTION_KEY_COLx);
将行引脚设置为上拉,并配置行引脚复用功能。
PAD_PullCtrl(pad_rowx, GPIO_PuPd_UP); Pinmux_Config(pad_rowx, PINMUX_FUNCTION_KEY_ROWx);
初始化 Key-Scan 参数。
根据键盘选择按键行数和列数(一位对应一行或一列),并将工作模式设置为事件触发模式或常规扫描模式等。
KeyScan_StructInit(&KeyScan_InitStruct); KeyScan_InitStruct.KS_ColSel = 0xFF; //8 列 KeyScan_InitStruct.KS_RowSel = 0xFF; //8 行 KeyScan_InitStruct.KS_WorkMode = KS_EVENT_TRIGGER_MODE; KeyScan_Init(KeyScan, &KeyScan_InitStruct);
KeyScan_StructInit(&KeyScan_InitStruct); KeyScan_InitStruct.KS_ColSel = 0xFF; //8 列 KeyScan_InitStruct.KS_RowSel = 0xFF; //8 行 KeyScan_InitStruct.KS_WorkMode = KS_REGULAR_SCAN_MODE; KeyScan_Init(KeyScan, &KeyScan_InitStruct);
使能 Key-Scan 中断,并注册 Key-Scan 中断处理函数。
使能 Key-Scan。
KeyScan_Cmd(KeyScan, ENABLE);
等待并处理 Key-Scan 中断。
按键卡滞处理
当出现按键卡滞时,执行以下步骤:
配置 Key-Scan 的引脚复用功能。
将列引脚设置为无上下拉,并配置列引脚复用功能。
PAD_PullCtrl(pad_colx, GPIO_PuPd_NOPULL); Pinmux_Config(pad_colx, PINMUX_FUNCTION_KEY_COLx);
将行引脚设置为上拉,并配置行引脚复用功能。
PAD_PullCtrl(pad_rowx, GPIO_PuPd_UP); Pinmux_Config(pad_rowx, PINMUX_FUNCTION_KEY_ROWx);
初始化 Key-Scan 参数。
根据键盘选择按键行数和列数(一位对应一行或一列),并将工作模式设置为常规扫描模式等。
KeyScan_StructInit(&KeyScan_InitStruct); KeyScan_InitStruct.KS_ColSel = 0xFF; //8 columns KeyScan_InitStruct.KS_RowSel = 0xFF; //8 rows KeyScan_Init(KeyScan, &KeyScan_InitStruct);
使能 Key-Scan 按键卡滞自动检测功能。
KeyScan_StuckAutoCmd(KeyScan, ENABLE);
设置卡滞时间阈值,并配置卡滞行检测时间和间隔时间。
KeyScan_SetStuckThreshold(KeyScan, 10); //stuck time threshold: 10ms KeyScan_StuckPeriodicalPull(KeyScan,2000,4000);//pull time:2000us, no pull time:4000us
使能 Key-Scan 按键卡滞和所有默认中断,并注册 Key-Scan 中断处理函数。
使能 Key-Scan。
KeyScan_Cmd(KeyScan, ENABLE);
等待并处理 Key-Scan 中断。
在按键卡滞事件中断中,获取行状态后,设置行默认状态以指示卡滞行,然后屏蔽卡滞行的所有按键。
row_status = KeyScan_GetStuckRow(KeyScan); KeyScan_SetStuckRow(KeyScan, row_status);
在所有默认中断中,将行默认状态重置为初始值,禁用所有默认中断,启用扫描事件中断和所有松开中断,这样除卡滞按键外的其他按键可正常工作。
KeyScan_INTConfig(KeyScan, KS_BIT_ALL_DEFAULT_INT_MASK, DISABLE); KeyScan_SetStuckRow(KeyScan, 0); KeyScan_INTConfig(KeyScan, KS_BIT_ALL_RELEASE_INT_MASK | KS_BIT_SCAN_EVENT_INT_MASK, ENABLE);
除卡滞按键外,其他按键的按下或松开将正常产生相应中断。