支持的芯片

Ameba SoC

RTL8721Dx

RTL8726E

RTL8720E

RTL8730E

支持状态

Y

N

N

N

概述

Key-Scan 作为一款键盘扫描设备,最多支持 8 x 8 的键盘矩阵,其行列可配置。

Key-Scan 同时支持多键检测,并且能在低功耗模式下工作。

系统框图

Key-Scan的框图如下所示:

../../_images/key_scan_block_diagram.svg

Key-Scan主要包含6个功能模块:

  • 中断控制:控制和管理中断

  • 寄存器及FIFO:配置 Key-Scan 参数和 FIFO

  • 时钟模块:131KHz时钟用于检测行键卡滞的情况

  • 键盘控制:扫描控制、唤醒控制、按键输入/输出控制

  • GPIO矩阵:16个GPIO实现8x8阵列

键盘矩阵

Key-Scan 的行列可配置,支持的最大列数或行数为 8。

../../_images/keypad_array.svg

8x8键盘矩阵配置

  • 初始状态下,所有列输出低电平,所有行设置为内部上拉输入。

  • 当有一个或多个按键按下(列与行之间短路)时,会触发内部状态机启动一次键盘扫描周期,以确定被按下按键所在的行列。

  • 状态机先将第一列设为输出低电平,其他列设为高阻态,然后扫描所有行来判断哪些按键被按下,接着将第二列设为输出低电平,依此类推,直到扫描完最后一列。

工作模式

Key-Scan 包含两种工作模式:事件触发模式和常规扫描模式。

工作模式

描述

事件触发模式

每次按键按下和松开操作,按键按下或松开事件仅在FIFO中仅记录一次

常规扫描模式

任何按键按下事件都会记录在 FIFO 中(仅记录按键按下事件),直到按键松开

下图展示了在按键按下和松开过程中,事件触发模式和常规扫描模式下 FIFO 的差异。

../../_images/difference_FIFO_items_between_two_work_modes.svg

FIFO机制

Key-Scan 的 FIFO 深度为 16,宽度为 12 位。其结构如下所示:

../../_images/FIFO_structure.svg

功能

参数描述

[8]

事件

  • 1:按键按下事件

  • 0:按键松开事件

[7:4]

行索引

  • 1:第 0 行

  • 2:第 1 行

  • 3:第 2 行

  • 8:第 7 行

[3:0]

列索引

  • 1:第 0 列

  • 2:第 1 列

  • 3:第 2 列

  • 8:第 7 列

低功耗管理

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 的事件触发模式或常规扫描模式,需执行以下步骤:

  1. 配置 Key-Scan 的引脚复用功能。

    1. 将列引脚设置为无上下拉,并配置列引脚复用功能。

      PAD_PullCtrl(pad_colx, GPIO_PuPd_NOPULL);
      Pinmux_Config(pad_colx, PINMUX_FUNCTION_KEY_COLx);
      
    2. 将行引脚设置为上拉,并配置行引脚复用功能。

      PAD_PullCtrl(pad_rowx, GPIO_PuPd_UP);
      Pinmux_Config(pad_rowx, PINMUX_FUNCTION_KEY_ROWx);
      
  2. 初始化 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);
    
  3. 使能 Key-Scan 中断,并注册 Key-Scan 中断处理函数。

  4. 使能 Key-Scan。

    KeyScan_Cmd(KeyScan, ENABLE);
    
  5. 等待并处理 Key-Scan 中断。

按键卡滞处理

当出现按键卡滞时,执行以下步骤:

  1. 配置 Key-Scan 的引脚复用功能。

    1. 将列引脚设置为无上下拉,并配置列引脚复用功能。

      PAD_PullCtrl(pad_colx, GPIO_PuPd_NOPULL);
      Pinmux_Config(pad_colx, PINMUX_FUNCTION_KEY_COLx);
      
    2. 将行引脚设置为上拉,并配置行引脚复用功能。

      PAD_PullCtrl(pad_rowx, GPIO_PuPd_UP);
      Pinmux_Config(pad_rowx, PINMUX_FUNCTION_KEY_ROWx);
      
  2. 初始化 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);
    
  3. 使能 Key-Scan 按键卡滞自动检测功能。

    KeyScan_StuckAutoCmd(KeyScan, ENABLE);
    
  4. 设置卡滞时间阈值,并配置卡滞行检测时间和间隔时间。

    KeyScan_SetStuckThreshold(KeyScan, 10);  //stuck time threshold: 10ms
    KeyScan_StuckPeriodicalPull(KeyScan,2000,4000);//pull time:2000us, no pull time:4000us
    
  5. 使能 Key-Scan 按键卡滞和所有默认中断,并注册 Key-Scan 中断处理函数。

  6. 使能 Key-Scan。

    KeyScan_Cmd(KeyScan, ENABLE);
    
  7. 等待并处理 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);
      
  8. 除卡滞按键外,其他按键的按下或松开将正常产生相应中断。