ARM 按键轮询编程实战

news2024/11/13 16:07:37

一、什么是按键

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");
        }
    }

}

在这里插入图片描述


源自朱有鹏老师.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/134807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【应急响应】 - Windows 排查分析

Windows 分析排查1. 文件分析1.1 开机启动文件1.2 temp 临时异常文件1.3 浏览器信息分析1.4 文件时间属性分析1.5 最近打开文件分析2. 进程分析2.1 可疑进程发现与关闭3. 系统信息3.1 windows 计划任务3.2 隐藏账户与发现3.2.1 隐藏账号的建立3.2.2 隐藏账号的删除3.3 补丁查看…

Java开发的党员管理系统党员会议系统党务管理系统

简介 Java开发的大学生党员管理系统&#xff0c;主要功能会议&#xff0c;会议记录&#xff0c;会议主持&#xff0c;设置参会人员&#xff0c;请假申请&#xff0c;会议内容附件上传下载&#xff0c;党费管理&#xff0c;入党积极分子预备党员管理&#xff0c;人员变动&#…

hcip实验

1.搭建拓扑 2.配置IP R14&#xff1a; [r14]ip route-static 0.0.0.0 0 145.1.1.2 [r14]acl 2000 [r14-acl-basic-2000]rule permit source any [r14]int GigabitEthernet 0/0/1 [r14-GigabitEthernet0/0/1]nat outbound 2000 [r14]int Tunnel 0/0/0 [r14-Tunnel0/0/0…

【2 - 随机森林 - 原理部分】菜菜sklearn机器学习

课程地址&#xff1a;《菜菜的机器学习sklearn课堂》_哔哩哔哩_bilibili 第一期&#xff1a;sklearn入门 & 决策树在sklearn中的实现第二期&#xff1a;随机森林在sklearn中的实现第三期&#xff1a;sklearn中的数据预处理和特征工程第四期&#xff1a;sklearn中的降维算法…

DDR3 数据传输 (四)

目录 引言 AXI从侧接口参数 AXI从侧接口信号 参考说明 引言 前文链接

【数学思维】数理经济中一些基本概念

【数学思维】数理经济中一些基本概念开集 open set 与闭集 closed set紧集 compact set集合有界 bounded set度量空间 metric space欧式空间 euclidean space闭包 closure上包络 upper envelope、下包络 lower envelope上极限 limit superior、下极限 limit inferior左连续、右…

RabbitMQ第五个实操小案例——主题交换机(TopicExchange)

文章目录RabbitMQ第五个实操小案例——主题交换机&#xff08;TopicExchange&#xff09;RabbitMQ第五个实操小案例——主题交换机&#xff08;TopicExchange&#xff09; TopicExchange 和 DirectExchange 这两种交换机非常相似&#xff0c;Topic类型的Exchange与Direct相比&…

JavaScript 面向对象的编程 (Code with mosh学习笔记)

JavaScript OOP Getting Start - 1- What is OOP 面向对象的编程是一种编程范例围绕对象而不是函数一些OOP语言 C#JavaRubyPythonJavaScript Getting Start - 2- Four Pillars of OOP OOP的4个概念&#xff1a; 封装 使用封装重新组合相关的变量和函数减少复杂性增加代码…

jrtt 某头条网页版 _signature参数逆向

本文仅供参考学习&#xff0c;如有侵权可联系本人 目标网站 aHR0cHM6Ly93d3cudG91dGlhby5jb20vYy91c2VyL3Rva2VuL01TNHdMakFCQUFBQWE0alpUdzhvRlZnaUJIREprMTA1NDdBVFBUb050aHlsVDRqWndZMmlrMXcvPw接口分析 token&#xff1a;需要采集用户 _signature&#xff1a;加密参数 ai…

【每日一leetcode】Day2 链表(简单)

一、剑指 Offer 06. 从尾到头打印链表 输入一个链表的头节点&#xff0c;从尾到头反过来返回每个节点的值&#xff08;用数组返回&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,3,2] 输出&#xff1a;[2,3,1] 限制&#xff1a; 0 < 链表长度 < 10000…

SCI论文解读复现【NO.3】MSFT-YOLO:基于变压器的改进YOLOv5钢表面缺陷检测(代码已复现)

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的SCI论文&am…

HCIP第三天ospf星型和全连实验

HCIP文章目录 文章目录HCIP文章目录ospf实验实验要求拓扑图R1/4/5为全连的MGRE结构所有私有网段可以互相通讯ospf实验 实验要求 1、R6为ISP只能配置ip地址&#xff0c;R1-5的环回为私有网段 2、R1/4/5为全连的MGRE结构&#xff0c;R1/2/3为星型的拓扑结构&#xff0c;R1为中心…

stm32平衡小车(1)---蓝牙模块及其bug处理

基于stm32c8t6开发板 一&#xff0c;蓝牙模块HC-05 1.外观 2.接线方式 TX----->PB10 RX----->PB11 VCC----->3.3V GND---->GND 3.AT模式 不用烧录代码&#xff0c;直接将c8t6和HC-05相连接&#xff0c;通过XCOM或者SSCOM软件便可以进入调试模式&a…

MySQL常见深入优化

一、分页查询优化 1. SQL语句准备 CREATE TABLE employees (id INT ( 11 ) NOT NULL AUTO_INCREMENT,name VARCHAR ( 24 ) NOT NULL DEFAULT COMMENT 姓名,age INT ( 11 ) NOT NULL DEFAULT 0 COMMENT 年龄,position VARCHAR ( 20 ) NOT NULL DEFAULT COMMENT 职位,hire_ti…

(Django+redis双机配置)ubuntu虚拟机配置redis,window中django访问

目录 Ubuntu虚拟机配置redis 进入root用户 配置redis服务 开启端口 1.设置密码 2.关闭只允许本机访问 3.关闭保护模式 双向ping测试 ubuntu开启SSH服务 Django中 Django中settings配置redis Ubuntu虚拟机配置redis 进入root用户 首先要进入root用户 后续一定保证要…

Spring Boot内存泄露,排查

背景 为了更好地实现对项目的管理&#xff0c;我们将组内一个项目迁移到MDP框架&#xff08;基于Spring Boot&#xff09;&#xff0c;随后我们就发现系统会频繁报出Swap区域使用量过高的异常。笔者被叫去帮忙查看原因&#xff0c;发现配置了4G堆内内存&#xff0c;但是实际使…

利用kafka发送系统

kafka是一种消息队列框架。 如果不用消息队列框架&#xff0c;就需要用阻塞队列来实现发送系统消息和系统通知 1.阻塞队列 阻塞队列是一种用来解决进程间通信的方式 阻塞队列依靠自带的两个方法put(往队列里面存数据)和take(从队列里面取数据) 2.Kafka kafka最早只是用来发…

CV | 计算机视觉中数据集的txt,csv数据预处理代码及实例

本文使用同一个数据集进行数据预处理练习&#xff0c;其中包含了人脸图片文件夹&#xff0c;CSV文件&#xff0c;txt文件。 数据集主要是针对于人脸照片进行年龄以及性别的预测&#xff0c;在导入模型签的一些简单的数据处理。 1.对人脸图片文件夹&#xff0c;txt文件的操作 …

详解 Redis 中的 RDB 快照

内存快照。所谓内存快照&#xff0c;就是指内存中的数据在某一个时刻的状态记录。这就类似于照片&#xff0c;当你给朋友拍照时&#xff0c;一张照片就能把朋友一瞬间的形象完全记下来。 对 Redis 来说&#xff0c;它实现类似照片记录效果的方式&#xff0c;就是把某一时刻的状…

1D/2D动画混合

1、动画混合 游戏动画中常见的功能就是在两个或者多个相似运动之间进行混合&#xff0c;比如&#xff1a; 根据角色的速度来混合行走和奔跑动画根据角色的转向来混合向左或向右倾斜的动作 可以理解是高级版的动画过渡&#xff0c;之前的动画过渡是处理两个不同类型动作之间切…