ARM 按键轮询编程实战

一、什么是按键

1、按键的物理特性

  1. 平时没人按的时候,弹簧把按键按钮弹开。此时内部断开的。
  2. 有人按下的时候,手的力量克服弹簧的弹力,将按钮按下,此时内部保持接通(闭合)状态;如果手拿开,则弹簧作用下按钮又弹开,同时内部又断开。
  3. 一般的按键都有 4 个引脚,这 4 个引脚成 2 对:其中一对是常开触点(像上面描述的不按则断开,按下则闭合);一对是常闭触点(平时不按时是闭合的,按下后是断开的)。

2、按键的电学原理(结合原理图分析)

  1. 硬件接法:
    SW5:GPH0_2
    SW6:GPH0_3
    SW7/8/9/10:GPH2_0/1/2/3

在这里插入图片描述

  1. 按键的电路连接分析:平时按钮没有按下时,按钮内部断开,GPIO 引脚处电压为高电平;当有人按下按钮时,按钮内部导通,外部 VDD 经过电阻和按钮连接到地,形成回路,此时 GPIO 引脚处电压就变成了低电平。此时 VDD 电压全部分压在了电阻上(这个电阻就叫分压电阻,这个电阻不能太小,因为电阻的功率是U*U/R)
  2. 总结:按键的工作方法:其实就是按键的按下与弹开,分别对应GPIO的两种电平状态(按下则 GPIO 为低电平,弹开则 GPIO 为高电平)。此时 SoC 内部可以通过检测这个 GPIO 的电平高低来判断按键有没有被按下,这个判断结果即可作为 SoC 的输入信号。

3、按键属于输入类设备

  1. 按键一般用来做输入设备(由人向 SoC 发送信息的设备,叫输入设备),由人向 SoC 发送按键信号(按键信号有 2 种:按下信号和弹开信号)。
  2. 有些设备就是单纯的输入设备,譬如按键、触摸屏等;有些设备就是单纯的输出设备,譬如LCD;还有一些设备是既能输入又能输出的,叫输入输出设备(IO),譬如串口。

4、按键的 2 种响应方法

  1. SoC 处理按键有 2 种思路:轮询方式和中断方式。
  2. 轮询方式,就是 SoC 主动的每隔一段时间去读取(按键所对应的)GPIO 的电平高低,以此获得按键信息;缺点在于 CPU 要一直注意按键事件,会影响 CPU 做其他事情。
  3. 中断方式,就是 SoC 事先设定好 GPIO 触发的中断所对应的中断处理程序 ISR,当外部按键按下或弹开时会自动触发 GPIO 对应的外部中断,导致 ISR 执行,从而自动处理按键信息。

二、轮询方式处理按键

1、X210开发板的按键接法

  1. 查原理图,找到按键对应的 GPIO:

SW5:GPH0_2
SW6:GPH0_3
SW7/8/9/10:GPH2_0/1/2/3

在这里插入图片描述


  1. 原理图上可以看出:按下时是低电平,弹起时是高电平。

2、按键对应的 GPIO 模式设置

  1. 按键接到 GPIO 上,按键按下还是弹起,决定外部电路的接通与否,从而决定这个 GPIO 引脚的电压是高还是低;这个电压可以作为这个 GPIO 引脚的输入信号,此时 GPIO 配置为输入模式,即可从 SoC 内部读取该引脚的电平为 1 还是 0(1 对应高电平,0 对应低电平)。
  2. GPH0CON(0xE0200C00)
    GPH0DAT(0xE0200C04)
    GPH2CON(0xE0200C40)
    GPH2DAT(0xE0200C44)

在这里插入图片描述

  1. 应该在 CON 寄存器中将 GPIO 设置为 input 模式,然后去读取 DAT 寄存器(读取到的相应位的值为 1 表示外部是高电平(对应按键弹起),读取到的位的值为 0 表明外部是低电平(按键按下))。

三、 轮询方式处理按键的程序流程

(1) 第一步,先初始化 GPIO 模式为 input;
(2) 第二步,循环读取 GPIO 的电平值,然后判断有无按键按下。


四、代码编写和调试

$ cat key.c
// 定义操作寄存器的宏
#define GPH0CON         0xE0200C00
#define GPH0DAT         0xE0200C04

#define GPH2CON         0xE0200C40
#define GPH2DAT         0xE0200C44

#define rGPH0CON        (*(volatile unsigned int *)GPH0CON)
#define rGPH0DAT        (*(volatile unsigned int *)GPH0DAT)
#define rGPH2CON        (*(volatile unsigned int *)GPH2CON)
#define rGPH2DAT        (*(volatile unsigned int *)GPH2DAT)


/************************************************************************************/
#define BIT_WIDTH_GPH0_CON              (4)

#define BIT_LOCATION_GPH0_2_FUNC        (0xf << 2 * BIT_WIDTH_GPH0_CON)
#define GPH0_2_FUNC_INPUT               (0x0 << 2 * BIT_WIDTH_GPH0_CON)
#define GPH0_2_FUNC_OUTPUT              (0x1 << 2 * BIT_WIDTH_GPH0_CON)
#define GPH0_2_FUNC_EXT_INT2            (0Xf << 2 * BIT_WIDTH_GPH0_CON)

#define BIT_LOCATION_GPH0_3_FUNC        (0xf << 3 * BIT_WIDTH_GPH0_CON)
#define GPH0_3_FUNC_INPUT               (0x0 << 3 * BIT_WIDTH_GPH0_CON)
#define GPH0_3_FUNC_OUTPUT              (0x1 << 3 * BIT_WIDTH_GPH0_CON)
#define GPH0_3_FUNC_EXT_INT3            (0Xf << 3 * BIT_WIDTH_GPH0_CON)


/************************************************************************************/
#define BIT_WIDTH_GPH2_CON              (4)


#define BIT_LOCATION_GPH2_0_FUNC        (0xf << 0 * BIT_WIDTH_GPH2_CON)
#define GPH2_0_FUNC_INPUT               (0x0 << 0 * BIT_WIDTH_GPH2_CON)
#define GPH2_0_FUNC_OUTPUT              (0x1 << 0 * BIT_WIDTH_GPH2_CON)
#define GPH2_0_FUNC_EXT_INT16           (0Xf << 0 * BIT_WIDTH_GPH2_CON)

#define BIT_LOCATION_GPH2_1_FUNC        (0xf << 1 * BIT_WIDTH_GPH2_CON)
#define GPH2_1_FUNC_INPUT               (0x0 << 1 * BIT_WIDTH_GPH2_CON)
#define GPH2_1_FUNC_OUTPUT              (0x1 << 1 * BIT_WIDTH_GPH2_CON)
#define GPH2_1_FUNC_EXT_INT17           (0Xf << 1 * BIT_WIDTH_GPH2_CON)

#define BIT_LOCATION_GPH2_2_FUNC        (0xf << 2 * BIT_WIDTH_GPH2_CON)
#define GPH2_2_FUNC_INPUT               (0x0 << 2 * BIT_WIDTH_GPH2_CON)
#define GPH2_2_FUNC_OUTPUT              (0x1 << 2 * BIT_WIDTH_GPH2_CON)
#define GPH2_2_FUNC_EXT_INT18           (0Xf << 2 * BIT_WIDTH_GPH2_CON)

#define BIT_LOCATION_GPH2_3_FUNC        (0xf << 3 * BIT_WIDTH_GPH2_CON)
#define GPH2_3_FUNC_INPUT               (0x0 << 3 * BIT_WIDTH_GPH2_CON)
#define GPH2_3_FUNC_OUTPUT              (0x1 << 3 * BIT_WIDTH_GPH2_CON)
#define GPH2_3_FUNC_EXT_INT19           (0Xf << 3 * BIT_WIDTH_GPH2_CON)

// 初始化按键
void key_init(void)
{
    // 设置GPHxCON寄存器,设置为输入模式
    // GPH0CON的bit8~15全部设置为0,即可
    rGPH0CON &= ~(BIT_LOCATION_GPH0_2_FUNC | BIT_LOCATION_GPH0_3_FUNC);
    // GPH2CON的bit0~15全部设置为0,即可
    rGPH2CON &= ~(BIT_LOCATION_GPH2_0_FUNC | BIT_LOCATION_GPH2_1_FUNC |
                  BIT_LOCATION_GPH2_2_FUNC | BIT_LOCATION_GPH2_3_FUNC);
}

void key_polling(void)
{
    // 依次,挨个去读出每个GPIO的值,判断其值为1还是0.如果为1则按键按下,为0则弹起
    // 轮询的意思就是反复循环判断有无按键,隔很短时间
    while (1)
    {
        // 对应开发板上标着LEFT的那个按键
        if (!(rGPH0DAT & (1<<2)))
        {
            printf("KEY LEFT press!\r\n");
        }

        // 对应开发板上标着DOWN的那个按键
        if (!(rGPH0DAT & (1<<3)))
        {
            printf("KEY DOWN press!\r\n");
        }

        // 对应开发板上标着UP的那个按键
        if (!(rGPH2DAT & (1<<0)))
        {
            printf("KEY UP press!\r\n");
        }

        // 对应开发板上标着RIGHT的那个按键
        if (!(rGPH2DAT & (1<<1)))
        {
            printf("KEY RIGHT press!\r\n");
        }

        // 对应开发板上标着BACK的那个按键
        if (!(rGPH2DAT & (1<<2)))
        {
            printf("KEY BACK press!\r\n");
        }

        // 对应开发板上标着MENU的那个按键
        if (!(rGPH2DAT & (1<<3)))
        {
            printf("KEY MENU press!\r\n");
        }
    }

}

在这里插入图片描述


源自朱有鹏老师.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值