嵌入式——按键原理和消抖方式

嵌入式——按键原理和消抖方式

一. 按键原理

如下图是一个4X3的按键原理图,左边KR是行,上面的KC是列。
这里以下降沿触发为例子来讲讲按键的原理和处理流程。所谓下降沿触发,就是从高电平到低电平即可触发,反之就是上升沿触发。

原理: 将列的输出电平拉高,然后依次拉低列,读取行的输入电平是否为低电平,若为低电平,则表示该按键被按下。

在这里插入图片描述

1. 按键配置

  • 根据原理图配置对应的GPIO口。
  • 将列(col)配置为输出口(OUTPUT),并设置成漏极开路(Open Drain)即高阻状态,使用外部上拉电阻即可产生高电平。
  • 将行(row)配置为输入口(INPUT),因为行默认是高电平,所以将GPIO模式设置成上拉模式(Pull up)。
  • 将按键设置为下降沿触发

2.按键扫描流程

1.禁用中断,防止扫描过程被干扰。
2.利用列的外部上拉电阻将所有列拉高为高电平,然后开始循环扫描按键是否被按下
3.循环扫描的流程
①将第一列拉低,然后扫描所有的行,一旦检测到行也是低电平,即表示按键被按下,如果行 没有低电平,则第一列扫描结束,将第一列拉高。
②然后拉低第二列,继续扫描所有行,依次扫描,直到扫描全部按键。
4.将所有列都拉低,为了防止下一次按键扫描无法将列一起拉高。
5.打开中断,将被按下的按键的行列数据拿出来。

static void key_scan_row(void)
{
    uint32_t col, col_mask, col_index;
    uint32_t row, row_mask, row_index, row_value;
    bool pressed = false;
    key_scan_data_t data = {0};
    uint32_t row_pin_mask = key_scan_env.config.row_pin_mask;
    uint32_t col_pin_mask = key_scan_env.config.col_pin_mask;

    // Disable IRQ
    gpio_set_interrupt(row_pin_mask, GPIO_TRIGGER_DISABLE);

    // All colume to HIGH
    pmu_pin_mode_set(col_pin_mask, PMU_PIN_MODE_PU);
    gpio_write(col_pin_mask, GPIO_HIGH);
    co_delay_us(KEY_SCAN_COL_OUTPUT_KEEP_TIME);
    pmu_pin_mode_set(col_pin_mask, PMU_PIN_MODE_OD);

    // Scan
    col_index = 0;
    for(col=0; col<KEY_SCAN_PIN_NUM_MAX; ++col)
    {
        col_mask = 1u << col;
        if(col_pin_mask & col_mask)
        {
            // Only current colume output LOW
            gpio_write(col_mask, GPIO_LOW);
            co_delay_us(KEY_SCAN_COL_OUTPUT_KEEP_TIME);

            // Read value
            row_value = (~gpio_read(row_pin_mask)) & row_pin_mask;

            // Current colume to HIGH
            pmu_pin_mode_set(col_pin_mask, PMU_PIN_MODE_PU);
            gpio_write(col_pin_mask, GPIO_HIGH);

            // Check ROW
            row_index = 0;
            for(row=0; row<KEY_SCAN_PIN_NUM_MAX; ++row)
            {
                row_mask = 1u << row;
                if(row_pin_mask & row_mask)
                {
                    if(row_value & row_mask)
                    {
                        data.num++;
                        data.val[col_index] |= 1u << row_index;
                    }

                    ++row_index;
                    if(row_index >= KEY_ROW_NUM)
                        break;
                }
            }

            if(data.val[col_index])
                pressed = true;

            // restore OD
            pmu_pin_mode_set(col_pin_mask, PMU_PIN_MODE_OD);

            ++col_index;
            if(col_index >= KEY_COL_NUM)
                break;
        }
    }

    // All colume to LOW
    gpio_write(col_pin_mask, GPIO_LOW);
    co_delay_us(KEY_SCAN_COL_OUTPUT_KEEP_TIME+50);

    // Enable IRQ
    gpio_set_interrupt(row_pin_mask, GPIO_BOTH_EDGE);

    if(pressed)
        key_pressed(data);
}

二. 按键抖动以及消抖方式

抖动原理

由于机械触点的弹性作用,按键在按下和松开的一瞬间都会伴随一阵抖动,一般是5~10ms左右,为了避免抖动带来的按下一次按键处理多次的问题,我们需要对按键进行消抖处理。
在这里插入图片描述

消抖的方式

大家可以参考一下这篇文章按键消抖及原理(硬件和软件方法详解)

对于硬件消抖一般适用于按键较少的情况下,因为按键消抖增加了电路的复杂性,增加了成本和体积,我们一般用软件消抖。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值