矩阵键盘
支持的芯片[ RTL8721Dx ]
概述
矩阵键盘作为一款键盘扫描设备,其行列数可自由配置,最多支持 8 x 8 的键盘矩阵配置。
矩阵键盘支持以下功能:
行数和列数可配置,适配不同大小的按键阵列
支持多键检测,最多可同时按下 6 个按键
支持两种工作模式:事件触发模式和常规扫描模式
支持按键卡滞检测
支持低功耗模式及唤醒功能
系统框图
矩阵键盘的框图如下所示:
矩阵键盘主要包含 5 个功能模块:
中断控制:控制和管理中断
寄存器及 FIFO:配置矩阵键盘参数和 FIFO
时钟模块:131KHz 时钟用于检测按键卡滞和低功耗唤醒
键盘控制:扫描控制、唤醒控制、按键输入/输出控制
GPIO 矩阵:16 个 GPIO 实现 8x8 阵列
键盘矩阵
矩阵键盘的行列可配置,支持的最大列数或行数均为 8。
8x8 键盘矩阵配置
按键被按下后,完整的扫描过程如下:
初始状态下,所有列输出低电平,所有行设置为内部上拉输入。
当有一个或多个按键按下(列与行之间短路)时,被按下按键所在行输入电平由高到低,此时会触发内部状态机启动进行键盘扫描,以确定被按下按键所在的行列。
状态机先将第一列设为输出低电平,其他列设为高阻态,然后扫描所有行来判断哪些按键被按下;接着将第二列设为输出低电平,将所有其他列置于高阻态;重复该过程,直到扫描完最后一列。
经过两次全键盘扫描,最终确认哪些按键被按下。
当所有按键被释放后,矩阵键盘仍会进行两轮全键盘扫描。当确认没有按键被按下后,结束扫描,停止状态机。
下图展示了 2 x 2 键盘按下按键后的扫描时序示意图。
键盘扫描时序
键盘扫描过程中有三个计时器可配置:
消抖计时:两次相邻的全键盘扫描组成一次完整的扫描周期,两次全键盘扫描之间都有一次消抖计时。而第一次全键盘扫描之前有一次额外的消抖计时。
扫描间隔计时:两次完整的扫描周期之间需要等待扫描间隔计时器计时结束。
所有按键释放计时:当所有按键被释放,矩阵键盘仍会有一次完整的扫描周期(两轮全键盘扫描),等扫描结束后确认无按键按下,释放计时器开始计时。等计时结束,状态机才会停止。
工作模式
矩阵键盘包含两种工作模式:事件触发模式和常规扫描模式。
工作模式 |
描述 |
|---|---|
事件触发模式 |
每次按键按下和松开操作,按键按下或松开事件在 FIFO 中仅记录一次 |
常规扫描模式 |
任何按键按下事件都会记录在 FIFO 中(仅记录按键按下事件),直到按键松开 |
下图展示了在按键按下和松开过程中,事件触发模式和常规扫描模式下 FIFO 的差异。
通常情况下,事件触发模式较为常用。该模式下,按键无须连续扫描,仅在按键状态发生改变时扫描键盘。
FIFO 机制
矩阵键盘的 FIFO 深度为 16,宽度为 12 位。其结构如下所示:
位 |
功能 |
参数描述 |
|---|---|---|
[8] |
事件 |
|
[7:4] |
行索引 |
|
[3:0] |
列索引 |
|
按键卡滞
在实际使用过程中可能会出现按键卡滞,如果按键未被及时松开,矩阵键盘状态机将持续进行扫描,无法进入 IDLE 状态。
为解决此问题,矩阵键盘支持自动检测按键卡滞的功能。
卡滞键检测:启用该功能后,若按键卡滞时间超过设定的阈值,该按键将被视为卡滞按键,并触发卡滞按键中断,用户可在卡滞按键中断中屏蔽卡滞按键所在行。
卡滞键屏蔽:通过读取按键卡滞状态寄存器获取卡滞的按键,并设置卡滞按键所在行的默认状态,矩阵键盘在扫描到该卡滞按键所在行时,会认为没有按键被按下,从而顺利进入 IDLE 状态。
卡滞键屏蔽解除:有两种方法
卡滞按键被释放后,将触发卡滞按键中断,用户可在该中断中解除卡滞按键所在行的屏蔽状态
非卡滞按键所在行的按键被按下,此时触发扫描状态机,产生扫描中断,用户可在中断中解除卡滞按键所在行的屏蔽状态
备注
卡滞按键被屏蔽后:
卡滞按键同一行的其他按键按下,不会触发矩阵键盘的扫描状态机
非卡滞按键所在行的按键按下才能触发矩阵键盘的扫描状态机。在扫描状态机唤醒后,如果卡滞按键所在行的屏蔽状态未被解除,所在行的其他按键仍然无法被识别,非卡滞行按键正常识别。
用法
正常工作模式
使用矩阵键盘的事件触发模式或常规扫描模式,需执行以下步骤:
配置矩阵键盘的引脚复用功能。
将列引脚设置为无上下拉,并配置列引脚复用功能。
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);
初始化矩阵键盘参数。
根据键盘选择按键行数和列数(一位对应一行或一列),并将工作模式设置为事件触发模式或常规扫描模式等。
事件触发模式: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);
使能矩阵键盘中断,并注册矩阵键盘中断处理函数。
使能矩阵键盘。
KeyScan_Cmd(KeyScan, ENABLE);
等待并处理矩阵键盘中断。
按键卡滞处理
当出现按键卡滞时,执行以下步骤:
配置矩阵键盘的引脚复用功能。
将列引脚设置为无上下拉,并配置列引脚复用功能。
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);
初始化矩阵键盘参数。
根据键盘选择按键行数和列数(一位对应一行或一列),并将工作模式设置为常规扫描模式等。
KeyScan_StructInit(&KeyScan_InitStruct); KeyScan_InitStruct.KS_ColSel = 0xFF; //8 columns KeyScan_InitStruct.KS_RowSel = 0xFF; //8 rows KeyScan_Init(KeyScan, &KeyScan_InitStruct);
使能矩阵键盘按键卡滞自动检测功能。
KeyScan_StuckAutoCmd(KeyScan, ENABLE);
设置卡滞时间阈值,并配置卡滞行检测时间和间隔时间。
KeyScan_SetStuckThreshold(KeyScan, 10); //stuck time threshold: 10ms KeyScan_StuckPeriodicalPull(KeyScan,2000,4000);//pull time:2000us, no pull time:4000us
使能矩阵键盘按键卡滞和所有默认中断,并注册矩阵键盘中断处理函数。
使能矩阵键盘。
KeyScan_Cmd(KeyScan, ENABLE);
等待并处理矩阵键盘中断。
在按键卡滞事件中断中,获取行状态后,设置行默认状态以指示卡滞行,然后屏蔽卡滞行的所有按键。
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);
除卡滞按键外,其他按键的按下或松开将正常产生相应中断。
Raw API
KSCAN Exported Types
-
struct KeyScan_InitTypeDef
KSCAN Init structure definition.
Public Members
-
u32 KS_ClkDiv
Specifies KeyScan clock divider. Scan_clk = Bus clock/(KS_ClkDiv+1). This parameter must be set to a value in the 0x0-0xfff range.
-
u32 KS_WorkMode
Specifies the KeyScan operating mode. This parameter can be a value of KSCAN Work Mode Definitions
-
u32 KS_RowSel
Specifies which rows are active. This parameter must be set to a value in the 0x1-0xff range.
-
u32 KS_ColSel
Specifies which columns are active. This parameter must be set to a value in the 0x1-0xff range.
-
u32 KS_DebounceCnt
Specifies the debounce counter value. Debounce timer = (KS_DebounceCnt + 1) * Scan_clk. This parameter must be set to a value in the 0x0-0xfff range.
-
u32 KS_IntervalCnt
Specifies the scan interval counter value. Interval timer = (KS_IntervalCnt + 1) * Scan_clk. This parameter must be set to a value in the 0x0-0xfff range.
-
u32 KS_ReleaseCnt
Specifies the all-release counter value. Release timer = (KS_ReleaseCnt + 1) * Scan_clk. This parameter must be set to a value in the 0x0-0xfff range.
-
u32 KS_LimitLevel
Specifies the maximum number of keys that can be pressed simultaneously. This parameter can be a value of KSCAN FIFO Limit Level Control
-
u32 KS_ThreholdLevel
Specifies the KeyScan FIFO threshold level for the KS_FIFO_FULL interrupt. This parameter can be a value of KSCAN FIFO Threshold Level Control
-
u32 KS_OverCtrl
Specifies KeyScan FIFO over control. This parameter can be a value of KSCAN FIFO Overflow Control
-
u32 KS_ClkDiv
KSCAN Exported Constants
KSCAN All Interrupt Clear
/* Clear bits for all KSCAN interrupts. */
#define KS_BIT_ALL_INT_CLR (KS_BIT_ALL_DEFAULT_INT_CLR | \
KS_BIT_STUCK_INT_CLR | \
KS_BIT_FIFO_LIMIT_INT_CLR | \
KS_BIT_FIFO_OV_INT_CLR | \
KS_BIT_SCAN_FINISH_INT_CLR | \
KS_BIT_ALL_RELEASE_INT_CLR)
KSCAN All Interrupt Mask
/* Mask bits for all KSCAN interrupts. */
#define KS_BIT_ALL_INT_MSK (KS_BIT_ALL_DEFAULT_INT_MASK | \
KS_BIT_STUCK_EVENT_INT_MASK | \
KS_BIT_SCAN_EVENT_INT_MASK | \
KS_BIT_FIFO_LIMIT_INT_MASK | \
KS_BIT_FIFO_OV_INT_MASK | \
KS_BIT_FIFO_FULL_INT_MASK | \
KS_BIT_SCAN_FINISH_INT_MASK | \
KS_BIT_FIFO_NOTEMPTY_INT_MASK | \
KS_BIT_ALL_RELEASE_INT_MASK)
KSCAN FIFO Limit Level Control
/* Check if FIFO limit level value is valid. */
#define IS_KS_FIFO_LIMIT_LEVEL ((DATA_NUM) <= 6)
KSCAN FIFO Overflow Control
/* Reject new data when FIFO full. */
#define KS_FIFO_OVER_CTRL_DIS_NEW ((u32)0x00000000)
/* Discard oldest data when FIFO full. */
#define KS_FIFO_OVER_CTRL_DIS_LAST ((u32)0x00000001)
/* Check if FIFO overflow control value is valid. */
#define IS_KS_FIFO_OVER_CTRL (((CTRL) == KS_FIFO_OVER_CTRL_DIS_NEW) || \
((CTRL) == KS_FIFO_OVER_CTRL_DIS_LAST))
KSCAN FIFO Threshold Level Control
/* Check if FIFO threshold level value is valid. */
#define IS_KS_FIFO_TH_LEVEL (((DATA_NUM) > 0) && ((DATA_NUM) < 16))
KSCAN Peripheral Definitions
/* Check if KSCAN peripheral is valid. */
#define IS_KEYSCAN_ALL_PERIPH ((PERIPH) == KEYSCAN_DEV || (PERIPH) == KEYSCAN_DEV_S)
KSCAN Work Mode Definitions
/* Regular scan mode selection. */
#define KS_REGULAR_SCAN_MODE ((u32)0x00000000)
/* Event trigger mode selection. */
#define KS_EVENT_TRIGGER_MODE ((u32)0x00000001)
/* Check if KSCAN work mode is valid. */
#define IS_KS_WORK_MODE (((MODE) == KS_REGULAR_SCAN_MODE) || \
((MODE) == KS_EVENT_TRIGGER_MODE))
KSCAN Exported Functions
-
void KeyScan_ClearFIFOData(KSCAN_TypeDef *KeyScan)
Clear the FIFO data.
- 参数:
KeyScan -- selected KeyScan peripheral.
-
void KeyScan_ClearINT(KSCAN_TypeDef *KeyScan, u32 KeyScan_IT)
Clear the specified KeyScan interrupt pending bits.
- 参数:
KeyScan -- selected KeyScan peripheral.
KeyScan_IT --
specifies the KeyScan interrupt to be cleared. This parameter can be one or combinations of the following values:
KS_BIT_ALL_DEFAULT_INT_CLR: all default flag
KS_BIT_STUCK_INT_CLR: Stuck event interrupt flag
KS_BIT_FIFO_LIMIT_INT_CLR: FIFO limit interrupt flag
KS_BIT_FIFO_OV_INT_CLR: FIFO overflow interrupt flag
KS_BIT_SCAN_FINISH_INT_CLR: Scan finish interrupt flag
KS_BIT_ALL_RELEASE_INT_CLR: All Release interrupt flag
备注
KS_BIT_SCAN_EVENT_INT_STATUS is automatically cleared by hardware when the data is read.
KS_BIT_FIFO_FULL_INT_STATUS is automatically cleared by hardware when the buffer level goes below the KS_FIFO_TH_LEVEL threshold.
KS_BIT_FIFO_NOTEMPTY_INT_STATUS is automatically cleared by hardware when the FIFO is empty.
-
void KeyScan_Cmd(KSCAN_TypeDef *KeyScan, u8 NewState)
Enable or disable the specified KeyScan peripheral.
- 参数:
KeyScan -- selected KeyScan peripheral.
NewState -- new state of the KeyScan peripheral. This parameter can be: ENABLE or DISABLE.
-
u8 KeyScan_GetDataNum(KSCAN_TypeDef *KeyScan)
Get the number of entries in the KeyScan FIFO.
- 参数:
KeyScan -- selected KeyScan peripheral.
- 返回:
Number of entries currently in the KeyScan FIFO.
-
bool KeyScan_GetFIFOState(KSCAN_TypeDef *KeyScan, u32 KeyScan_Flag)
Get the status of the KeyScan FIFO.
- 参数:
KeyScan -- selected KeyScan peripheral.
KeyScan_Flag --
specifies the flag to check. This parameter can be one of the following values:
KS_BIT_FIFO_FULL
KS_BIT_FIFO_EMPTY
- 返回:
The new state of the specified flag:
TRUE: flag is set
FALSE: flag is not set
-
u32 KeyScan_GetINT(KSCAN_TypeDef *KeyScan)
Get KeyScan interrupt status.
- 参数:
KeyScan -- selected KeyScan peripheral.
- 返回:
Interrupt status.
-
u32 KeyScan_GetRawINT(KSCAN_TypeDef *KeyScan)
Get KeyScan Raw Interrupt Status.
- 参数:
KeyScan -- selected KeyScan peripheral.
- 返回:
Raw interrupt status.
-
u32 KeyScan_GetStuckRow(KSCAN_TypeDef *KeyScan)
Get the stuck-row default status.
- 参数:
KeyScan -- selected KeyScan peripheral.
- 返回:
Default status of row0 to row7:
1: row stuck
0: row not stuck
-
void KeyScan_INTConfig(KSCAN_TypeDef *KeyScan, u32 KeyScan_IT, u8 newState)
Enable or disable the specified KeyScan interrupt sources.
- 参数:
KeyScan -- selected KeyScan peripheral.
KeyScan_IT --
specifies the KeyScan interrupt sources to be enabled or masked. This parameter can be one or combinations of the following values:
KS_BIT_ALL_DEFAULT_INT_MASK: Unmask all default interrupt
KS_BIT_STUCK_EVENT_INT_MASK: Unmask Stuck event interrupt
KS_BIT_SCAN_EVENT_INT_MASK: Unmask Scan event interrupt
KS_BIT_FIFO_LIMIT_INT_MASK: Unmask FIFO limit interrupt
KS_BIT_FIFO_OV_INT_MASK: Unmask FIFO overflow interrupt
KS_BIT_FIFO_FULL_INT_MASK: Unmask FIFO full interrupt
KS_BIT_SCAN_FINISH_INT_MASK: Unmask scan finish interrupt
KS_BIT_FIFO_NOTEMPTY_INT_MASK: Unmask FIFO nonempty interrupt
KS_BIT_ALL_RELEASE_INT_MASK: Unmask All Release interrupt
newState -- new state of the specified KeyScan interrupt sources. This parameter can be: ENABLE or DISABLE.
-
void KeyScan_Init(KSCAN_TypeDef *KeyScan, KeyScan_InitTypeDef *KeyScan_InitStruct)
Initialize the KeyScan peripheral according to the specified parameters in the KeyScan_InitStruct.
- 参数:
KeyScan -- selected KeyScan peripheral.
KeyScan_InitStruct -- pointer to a KeyScan_InitTypeDef structure that contains the configuration information for the specified KeyScan peripheral.
-
void KeyScan_Read(KSCAN_TypeDef *KeyScan, u32 *outBuf, u8 count)
Read data from KeyScan FIFO.
- 参数:
KeyScan -- selected KeyScan peripheral.
outBuf -- buffer to save data read from KeyScan FIFO.
count -- number of entries to read.
-
void KeyScan_SetColRow(KSCAN_TypeDef *KeyScan, u32 column_sel, u32 row_sel)
Set the active columns and rows for KeyScan.
- 参数:
KeyScan -- selected KeyScan peripheral.
column_sel -- Specifies which columns are active. This parameter must be set to a value in the 0x1-0xff range.
row_sel -- Specifies which rows are active. This parameter must be set to a value in the 0x1-0xff range.
-
void KeyScan_SetStuckRow(KSCAN_TypeDef *KeyScan, u32 Status)
Set the stuck-row default status.
- 参数:
KeyScan -- selected KeyScan peripheral.
Status -- row default status. one bit one row, bit 0 means row0, bit 7 means row7. 1: row stuck 0: row not stuck
-
void KeyScan_SetStuckThreshold(KSCAN_TypeDef *KeyScan, u32 ThresholdMs)
Set the stuck key detection time threshold.
- 参数:
KeyScan -- selected KeyScan peripheral.
ThresholdMs -- stuck key detection time threshold in milliseconds. ThresholdMs = (Threshold +1)* Scan_clk(ms). Threshold must be set to a value in the 0x0-0x7fffffff range.
-
void KeyScan_StructInit(KeyScan_InitTypeDef *KeyScan_InitStruct)
Fill each KeyScan_InitStruct member with its default value.
- 参数:
KeyScan_InitStruct -- pointer to an KeyScan_InitTypeDef structure which will be initialized.
-
void KeyScan_StuckAutoCmd(KSCAN_TypeDef *KeyScan, u8 NewState)
Enable or disable the KeyScan stuck auto check function.
- 参数:
KeyScan -- selected KeyScan peripheral.
NewState -- new state of the KeyScan stuck auto check function. This parameter can be: ENABLE or DISABLE.
-
void KeyScan_StuckPeriodicalPull(KSCAN_TypeDef *KeyScan, u32 PullUpUs, u32 NoPullUs)
Set the stuck-row periodic detection timing.
- 参数:
KeyScan -- selected KeyScan peripheral.
PullUpUs -- stuck-row detection pull-up time in microseconds. PullUpUs = (PullUpCnt +1)* clk_131k(us), max value is 15625us. PullUpCnt must be set to a value in the 0x0-0x7ff range.
NoPullUs -- stuck-row detection no-pull time in microseconds. When NoPullUs is 0, disable stuck-row detection. When NoPullUs is not 0, NoPullUs = (NoPullCnt +1)* clk_131k(us), max value is 31250us. NoPullUs can be set to a value in the 0x0-0xfff range.