正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-17讲 定时器按键消抖

前言:

本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》

正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档

正文:

本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第17 讲” 的读书笔记。第17讲主要是介绍I.MX6U处理器的EPIT定时器的按键消抖。本节将参考正点原子的视频教程第17讲和配套的正点原子开发指南文档进行学习。

0. 概述

在第15章和第17章实验都使用到了按键,用到按键就要处理因为机械结构带来的抖动问题,也就是按键消抖。前面的时延中都是直接使用了延时函数来实现消抖,因为简单,但是直接使用延时函数来实现消抖会浪费CPU的性能,因为在延时函数里面CPU什么都做不了。如果按键使用中断的话更不能再中断里面使用延时函数,因为中断服务函数要快进快出!本章我们学习如何使用定时器来实现按键消抖,使用定时器既可以实现按键消抖,而且也不会浪费CPU性能,这个也是Linux驱动里面按键消抖的做法。

1. 定时器按键消抖简介

按键消抖的原理已经在第十五章详细的讲解过了,起始就是在按键按下以后延时一段时间再去读取按键值,如果此时按键值还有效那就表示这是一次有效的按键,中间的延时就是消抖的。

但是这有一个缺点,就是已按时函数会浪费CPU性能,应为延时函数就是空跑。如果按键是用中断方式实现的,那就更不应该在中断服务函数里使用延时函数,因为中断服务函数最基本的要求就是快进快出!上一章我们学习了EPIT定时器,定时器设置好定时时间,然后CPU就可以做其他事情去了,定时时间到了以后就会触发中断,然后在中断中做相应的处理即可。

因此,我们可以借助定时器来实现消抖,

  1. 按键采用中断驱动的方式,当按下按键触发按键中断,在按键中断中开启一个定时器,
  2. 定时周期为10ms,当定时时间到了以后就会触发定时器中断
  3. 最后在定时器中断处理函数中读取按键的值,如果按键还是按下的状态那就表示这是一次有效的按键。

定时器按键消抖如下图所示:

在图19.1.1中的t1~t3这一段时间就是按键抖动,是需要消除的。设置按键为下降沿触发,因此会在t1,t2,和t3这三个时刻触发那件中断,每次进入中断处理函数都会重开定时器中断,所以会在t1,t2,和t3这三个时刻开定时器中断。但是t1~t2和t2~t3这两段时间是小于我们设置的定时器中断周期(也就是消抖时间,比如10ms),所以虽然t1开启了定时器,但是定时器时间没有到呢t2时刻就重置了定时器,最终之后t3时刻开启的定时器能完整的完成整个定时周期并触发中断,我们就可以在中断处理函数里面做按键处理了,这就是定时器完成按键消抖的原理,Linux里面的按键驱动用的就是这个原理!

关于定时器消毒的原理就介绍到这里,接下来讲解如何使用EPIT1来配置按键KEY来实现具体的消抖,步骤如下:

  1. 配置按键IO中断
    配置按键所使用的IO,因为要使用到中断驱动按键,所以要配置IO的中断模式。
  2. 初始化消抖用的定时器
    上面已经讲的很清楚了,消抖要用定时器来完成,所以需要初始化一个定时器,这是使用上一章讲解的EPIT1定时器,也算是对EPIT1定时器的一次巩固。定时器的定时周期为10ms,也可以根据实际情况调整定时周期。
  3. 编写中断处理函数
    需要编写两个中断处理器函数:按键对应的GPIO中断处理函数和EPIT1定时器的中断处理函数。在按键的中断处理函数中主要用于开启EPIT1定时器,EPIT1定时器处理函数才是重点,按键要做的具体任务都是在定时器EPIT1的中断处理函数中完成的,比如控制蜂鸣器打开或关闭。

2. 定时器按键消抖程序编写

更具上面分析的定时器按键消抖的原理和定时器按键消抖实验的步骤,编写定时器按键消抖程序源码如下:

bsp/keyfilter/bsp_keyfilter.h

#ifndef __BSP_KEYFILTER_H__
#define __BSP_KEYFILTER_H__#include "imx6u.h"void keyfilter_init(void);
void keyfilter_timer_init(int value);
void keyfilter_timer_stop(void);
void keyfilter_timer_restart(int value);
void keyfilter_timer_irqhandler(IRQn_Type irq, void *userparam);
void gpio1_16_31_irqhandler(IRQn_Type irq, void *userparam);#endif

bsp/keyfilter/bsp_keyfilter.c 

#include "bsp_keyfilter.h"
#include "bsp_beep.h"
#include "bsp_led.h"
#include "bsp_int.h"
#include "bsp_gpio.h"
#include "bsp_epittimer.h"void keyfilter_init(void)
{/* GPIO1_IO18 */gpio_pin_config_t config;/* 1. 初始化IO复用,复用为GPIO1_IO18 */IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);/* 2. 设置 UART1_CTS_B IO 的电气特性 */IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xf080);/* 3. 初始化 GPIO1_IO18 设置为输入 */config.directioin = kGPIO_DigitalInput;config.intMode = kGPIO_FalllingEdgeInt;gpio_init(GPIO1, 18, &config);/* 启用GIC IRQ */GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);/* 注册IRQ处理函数 */system_irqhandler_register(GPIO1_Combined_16_31_IRQn, gpio1_16_31_irqhandler, NULL);/* EPIT1定时器初始化 */keyfilter_timer_init(66000000/100);/* 启用gpio中断 */gpio_int_enable(GPIO1, 18);
}void keyfilter_timer_init(int value){EPIT1->CR = 0;EPIT1->CR = (1 << 24 )| (1 << 3) | (1 << 2) | (1 << 1);EPIT1->LR = value;EPIT1->CMPR = 0;/* 使能GIC EPIT1_IRQn 中断 */GIC_EnableIRQ(EPIT1_IRQn);/* 注册中断处理函数 */system_irqhandler_register(EPIT1_IRQn, keyfilter_timer_irqhandler, NULL);
}void keyfilter_timer_stop(void)
{EPIT1->CR &= ~(1 << 0);
}void keyfilter_timer_restart(int value){EPIT1->CR &= ~(1 << 0);		/* 关闭EPIT1 */EPIT1->LR = value;			/* EPIT1加载值寄存器 */EPIT1->CR |= (1 << 0);		/* 打开EPIT1 */
}void keyfilter_timer_irqhandler(IRQn_Type irq, void *userparam){static int beep_state = 0;if(EPIT1->SR & (1 << 0)){					/* 检查EPIT1中断标志 */keyfilter_timer_stop();					/* 关闭EPIT1定时器 */if(gpio_pinread(GPIO1, 18) == 0)		/* 检查gpio引脚电平值 */{beep_state = !beep_state;			/* 翻转蜂鸣器 */beep_switch(beep_state);}}/* 清除中断标志位 */EPIT1->SR |= (1<<0);
}void gpio1_16_31_irqhandler(IRQn_Type irq, void *userparam){if(GPIO1->ISR & (1 << 18)){keyfilter_timer_restart(66000000/100);		/* 重启EPIT1定时器,定时器周期10ms */}/* 清除中断标志位 */gpio_int_cleanFlag(GPIO1, 18);
}

在如上的源码中,初始化按键KEY0 对应GPIO1_IO18的 IO 复用,IO特性,启用IO中断,并注册GPIO1_IO18的中断处理函数,在按键中断处理函数中重启 EPIT1定时器设置定时周期为10ms,当定时周期完成时触发EPIT1定时器比较事件中断,在EPIT1定时器中断里再次检查gpio引脚的输入电平如果还是有效说明此次按键按下是有效的,此时在EPIT1定时器中断里翻转蜂鸣器的鸣叫。

3. 编译烧写SD卡验证实验结果

译修改主频后源码烧录SD卡验证本节的EPIT定时器消抖实验是否生效。预期烧录SD卡后正点原子I.MX6ULL ALPHA/Mini 开发板后,按下按键蜂鸣器鸣叫,再次按下按键蜂鸣器停止鸣叫,多次测试按键按下都能翻转蜂鸣器开关。

我本地验证的结果是EPIT定时器按键消抖实验结果正常,多次按下按键都能正确的翻转蜂鸣器鸣叫开关。

4. 总结和实验遇到的问题记录

4.1 问题1:EPIT定时器消抖实验程序烧录SD,发现有时按下并松开按键后蜂鸣器只鸣叫一声就停止,预期应该一直鸣叫。

原因分析如下:

  1. 由于按键的机械结构,不仅仅在按键按下的瞬间有电平的多次抖动,从而在按键按下的瞬间多次在按键gpio电平的下降沿触发GPIO中断,进而重置EPIT1定时器最终出发EPIT1定时器中断。
  2. 按键的机械结构决定了,在按键松开的瞬间也有多次的gpio引脚电平抖动,也会在按键松开的瞬间由于抖动在电平的下降沿触发GPIO中断,进而重置EPIT1定时器最终出发EPIT1定时器中断。
  3. 由上分析可知,由于按键的机械结构,在按键按下的时会有电平抖动从而触发GPIO中断;在按键松开的时同样也会有电平抖动从而触发GPIO中断;
    所以,必须在EPIT1定时器中断里再次检查 GPIO 引脚的电平是否有效,对于本实验,在按键按下的时候EPIT1中断处理函数读取到的gpio引脚为低电平证明按键按下有效。
    (EPIT1定时中断处理函数里读取到gpio引脚为高电平,说明是按键松开。)

5. 结束

本文至此结束

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

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

相关文章

计算机网络安全控制技术

1.防火墙技术 防火墙技术是近年来维护网络安全最重要的手段&#xff0c;但是防火墙不是万能的&#xff0c;需要配合其他安全措施来协同 2.加密技术 目前加密技术主要有两大类&#xff1a;对称加密和非对称加密 3.用户识别技术 核心是识别网络者是否是属于系统的合法用户 …

【设计模式深度剖析】【1】【结构型】【代理模式】| 玩游戏打怪、升级为例加深理解

&#x1f448;️上一篇:创建型设计模式对比 | 下一篇:装饰器模式&#x1f449;️ 目 录 代理模式定义英文原话直译如何理解&#xff1f; 3个角色UML类图1. 抽象主题&#xff08;Subject&#xff09;角色2. 代理类&#xff1a;代理主题&#xff08;Proxy Subject&#xff0…

UE5 OnlineSubsystem Steam创建会话失败解决方法

连接上Steam但是创建会话失败 解决方法 在DefaultEngine.ini中加上bInitServerOnClienttrue,这个其实在官方文档里用注释给出了&#xff0c;直接取消注释就行 删除项目目录中的Saved、Internmediate、Binaries目录 右键你的项目.uproject选择Generate Visual Studio project f…

ASP.Net MVC在控制台添加视图时没有模型类并且不能添加视图

情况如下&#xff1a; 解决方法&#xff1a; 1.查看vs能否创建asp.net mvc项目&#xff0c;这种情况一般是更换了vs打开老项目 2.点击跳转至修改安装选项界面 3.选择安装项即可 如果以上都有&#xff1a; 看看你的视图文件是否存在在项目中 也不能点击添加&#xff0c;如果…

探索数值分析的奥秘:掌握NumPy与Pandas基础

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、NumPy&#xff1a;数值计算的效率提升器 二、Pandas&#xff1a;数据处理与分析的利器 …

Linux文本三剑客之sed

set的定义&#xff1a; sed是一种流编辑器&#xff0c;流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。 sed编辑器可以根据命令来处理数据流中的数据&#xff0c;这些命令要么从命令行中输入&#xff0c;要么存储在一个命令文本文件中。 sed的执行过程&a…

Nextjs 动态路由获取参数

目录 一、创建page目录下的路由文件 二、通过useRouter来获取动态参数 先看官方文档&#xff1a;Routing: Dynamic Routes | Next.js 使用Nextjs13版本参考官方文档后实现仍有问题&#xff0c;网上的材料大多和官网一致&#xff0c;经过测试后&#xff0c;我找到了这个解决方…

【日记】今天好困(407 字)

正文 4T 硬盘降价了&#xff0c;好心动。虽然只降了 10 块钱……. 为什么硬盘这么贵啊&#xff01;哼。 柜面上杂事好多。虽然一天到晚见不到几个客户&#xff0c;但杂事就是很多。一个头两个大。也不知道从哪儿冒出来的这么多事。 芒果干到了&#xff01;还没去取&#xff0c;…

sql把一个表的某几列的数据存到另一个表里

一.如何用slq语句把一个表中的某几个字段的数据插入到另一个新表中&#xff0c;就要用下面这条slq语句&#xff1a; insert into 表名1(字段1,字段2) select 字段1,字段2 from 表名2 这里有一点值得注意的是这2个字段要一一对应&#xff0c;并且按顺序。 二.如果另一个表是…

JAVASE之类和对象(1)

路虽远&#xff0c;行则将至&#xff1b;事虽难&#xff0c;做则必成。 主页&#xff1a;趋早——Step 专栏&#xff1a;JAVASE gitte&#xff1a;https://gitee.com/good-thg 引言&#xff1a; 这篇文章我们只介绍前半部分&#xff0c;下一篇文章会介绍剩下的部分。 目录 一、…

LeetCode 面试150

最近准备面试&#xff0c;我以前不愿意面对的 现在保持一颗本心&#xff0c;就是专注于算法思想&#xff0c;语言基础的磨炼&#xff1b; 不为速成&#xff0c;不急功近利的想要比赛&#xff0c;或者为了面试。 单纯的本心&#xff0c;体验算法带来的快乐&#xff0c;是一件非常…

Python操作MySQL数据库的工具--sqlalchemy

文章目录 一、pymysql和sqlalchemy的区别二、sqlalchemy的详细使用1.安装库2.核心思想3.整体思路4.sqlalchemy需要连接数据库5.使用步骤1.手动提前创建数据库2.使用代码创建数据表3.用代码操作数据表3.1 增加数据3.2 查询数据3.3 删除数据3.4 修改数据 一、pymysql和sqlalchemy…

2025秋招深度学习基础面试题(一)

01. 卷积和BN如何融合提升推理速度 Conv和BN的融合:在网络的推理阶段,可以将BN层的运算融合到Conv层中,减少运算量,加速推理。本质上是修改了卷积核的参数,在不增加Conv层计算量的同时,略去了BN层的计算量。def fuse_conv_bn(conv, bn):std = (bn.running_var + bn.eps).…

数据仓库、数据中台、大数据平台之间的关系

数据行业经常会出现数据仓库、数据中台、大数据平台等概念&#xff0c;容易产生疑问&#xff0c;它们中间是相等&#xff0c;还是包含的关系&#xff1f; 数据中台和数据仓库概念的关系 数据中台概念是包含数据仓库的&#xff0c;数据仓库是数据中台中的一部分&#xff0c;包含…

探索Facebook:数字社交的新时代

Facebook&#xff0c;作为全球最大的社交网络平台之一&#xff0c;一直在引领着数字社交的发展潮流。随着科技的不断进步和社会的不断变迁&#xff0c;Facebook也在不断演进和创新&#xff0c;迎接着数字社交的新时代。本文将探索Facebook在数字社交领域的新发展&#xff0c;以…

Behind the Code:Polkadot 如何重塑 Web3 未来

2024 年 5 月 17 日 Polkadot 生态 Behind the Code 第二季第一集 《创造 Web3 的未来》正式上线。第一集深入探讨了 Polkadot 和 Web3 技术在解决数字身份、数据所有权和去中心化治理方面的巨大潜力。 &#x1f50d; 查看完整视频&#xff1a; https://youtu.be/_gP-M5nUidc?…

抖音视频怎么去水印保存部分源码|短视频爬虫提取收集下载工具

抖音视频怎么去水印保存部分源码|短视频爬虫提取收集下载工具 抖音视频去水印保存部分源码&#xff1a; 通过使用Python中的requests、re和os等库&#xff0c;可以编写如下代码来实现抖音视频去水印保存的功能。 短视频爬虫提取手机下载工具的使用方法&#xff1a; 该工具主…

BevDet-4d(2): 环境安装及效果展示

1. 环境安装 conda create -n bevdet python=3.8 conda activate bevdet ​ # 3 虚拟环境bevdet中安装torch pip install spconv pip install torch==1.10.0+cu113 torchvision==0.11.0+cu113 torchaudio==0.10.0 -f https://download.pytorch.org/whl/torch

【数理统计02】延森Jensen‘s不等式的证明

延森不等式&#xff08;Jensen’s Inequality&#xff09;是凸函数理论中的一个重要结果&#xff0c;广泛应用于概率论、统计学和优化理论等领域。这个不等式的基本形式是&#xff1a; 对于一个凸函数 f f f和一个随机变量 X X X&#xff0c;如果 E [ X ] \mathbb{E}[X] E[X]存…

安科瑞为河南省促进分布式光伏发电健康持续发展提供解决方案

1 光伏、储能运维市场分析 在光伏、储能行业飞速发展的同时&#xff0c;已建的光伏、风力发电站和储能系统的监控、运维管理项目的招标也非常多&#xff0c;2023年上半年&#xff0c;光伏电站开发企业运维招标规模28.6GW&#xff0c;同比增长204.3%&#xff0c;上述28.6GW招标…