支持的芯片
Ameba SoC |
RTL8721Dx |
RTL8726E |
RTL8720E |
RTL8730E |
---|---|---|---|---|
支持状态 |
Y |
N |
N |
N |
概述
Key-Scan 作为一款键盘扫描设备,最多支持 8 x 8 的键盘矩阵,其行列可配置。
Key-Scan 同时支持多键检测,并且能在低功耗模式下工作。
系统框图
Key-Scan的框图如下所示:
Key-Scan主要包含6个功能模块:
中断控制:控制和管理中断
寄存器及FIFO:配置 Key-Scan 参数和 FIFO
时钟模块:131KHz时钟用于检测行键卡滞的情况
键盘控制:扫描控制、唤醒控制、按键输入/输出控制
GPIO矩阵:16个GPIO实现8x8阵列
键盘矩阵
Key-Scan 的行列可配置,支持的最大列数或行数为 8。
8x8键盘矩阵配置
初始状态下,所有列输出低电平,所有行设置为内部上拉输入。
当有一个或多个按键按下(列与行之间短路)时,会触发内部状态机启动一次键盘扫描周期,以确定被按下按键所在的行列。
状态机先将第一列设为输出低电平,其他列设为高阻态,然后扫描所有行来判断哪些按键被按下,接着将第二列设为输出低电平,依此类推,直到扫描完最后一列。
工作模式
Key-Scan 包含两种工作模式:事件触发模式和常规扫描模式。
工作模式 |
描述 |
---|---|
事件触发模式 |
每次按键按下和松开操作,按键按下或松开事件仅在FIFO中仅记录一次 |
常规扫描模式 |
任何按键按下事件都会记录在 FIFO 中(仅记录按键按下事件),直到按键松开 |
下图展示了在按键按下和松开过程中,事件触发模式和常规扫描模式下 FIFO 的差异。
FIFO机制
Key-Scan 的 FIFO 深度为 16,宽度为 12 位。其结构如下所示:
位 |
功能 |
参数描述 |
---|---|---|
[8] |
事件 |
|
[7:4] |
行索引 |
|
[3:0] |
列索引 |
|
低功耗管理
Active模式
在Active模式下,Key-Scan 电路始终保持通电。
列扫描:当Key-Scan扫描第 x 列(x 表示任意一列)时,将第 x 列设置为低电平,同时将所有其他列置于高阻态(Hi-Z)。
行检测:设置列后,Key-Scan扫描所有行以检测哪些键被按下或释放,完成一次列扫描。
顺序扫描:Key-Scan按顺序扫描所有列,并周期性地逐列进行扫描。
Sleep模式
在实际应用中,Key-Scan保持在Active模式会非常耗电。为了节省功耗并优化性能,Key-Scan通常运行在Sleep模式。
低功耗状态:在Sleep模式下,CPU 进入低功耗状态以减少能耗。
唤醒机制:当有键被按下时,CPU 被唤醒,Key-Scan开始扫描以确定哪些键被按下。Key-Scan会在按键保持按下状态时持续扫描。
返回休眠状态:当所有键被释放且没有其他事件发生时,CPU 重新进入休眠状态。
按键卡滞
在某些应用中可能会出现按键卡滞的情况。如果没有应对方案,CPU 将保持活动状态持续进行键盘扫描,导致 CPU 无法进入低功耗模式,进而产生高功耗。
为解决此问题,Key-Scan 支持自动检测按键卡滞的功能。启用该功能后,若按键卡滞时间超过阈值,该按键将被视为卡滞按键。通过读取按键卡滞状态寄存器获取卡滞的按键,并设置卡滞按键所在行的默认状态,以便 CPU 进入低功耗模式。
为降低功耗,还可启用卡滞行检测功能,设置行引脚无上下拉检测时间间隔。
用法
正常工作模式
使用 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 | KS_BIT_STUCK_EVENT_INT_MASK, DISABLE); KeyScan_SetStuckRow(KeyScan, 0); KeyScan_INTConfig(KeyScan, KS_BIT_ALL_RELEASE_INT_MASK | KS_BIT_SCAN_EVENT_INT_MASK, ENABLE);
除卡滞按键外,其他按键的按下或松开将正常产生相应中断。