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

news2024/11/17 11:25:41

前言:

本文是根据哔哩哔哩网站上“正点原子[第二期]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.coloradmin.cn/o/1687691.html

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

相关文章

带你玩转OpenHarmony AI:打造智能语音子系统

简介 AI时代&#xff0c;智者当先&#xff0c;判断一个终端设备是否智能&#xff0c;语音能力是必不可缺的。智能家居、智慧厨房、智能汽车等等&#xff0c;一切衣食住行都在往智能方向发展&#xff0c;那我们该如何在OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&am…

海康监控web插件,跨域问题处理web-control

海康视频跨域问题处理web-control 海康监控视频&#xff0c;跨域处理&#xff0c;web-control修改案例 海康监控视频&#xff0c;跨域处理&#xff0c;web-control修改 海康监控&#xff0c;web-control&#xff0c;跨域播放&#xff0c;嵌套页面实现跨域播放 案例 能到做到…

【intel CPU】三代牙膏的对比

1、PC处理器的选择 制程工艺 传说的“intel7”,感觉就像老婆饼&#xff0c;并不是7nm。 2、12代到13代其实应该归为一代&#xff0c;那就是大核心不行就堆小核心 3、所以智能踢掉有小核的&#xff1b; 3.1、CPU规格 3.2 内存规格 3.3 封装规格 其他都是一样的&#xff1b; …

变量与常量

1.变量 数学中的定义&#xff1a; 变量&#xff1a;可变的数据称为变量 Java中定义&#xff1a; 内存中一块存储区域 该区域的数据可以在同一类型范围内不断变化 变量是程序中最基本的存储单元&#xff0c;包含了变量类型、变量名和存储的值 变量的作用就是在内存中保存…

uniapp微信小程序在ios端返回不显示弹窗的bug解决

这个问题其实是因为返回页面的时候弹的太快了导致的解决办法&#xff1a; 其实就是返回页面的弹窗加个延迟就好啦

新定义RD8T36P48点亮LED--汇编

其实汇编和C语言差不多&#xff0c;简单的东西用汇编挺好&#xff0c;中等及以上复杂度的程序还是C语言更灵活 直接在keil新建好工程&#xff0c;选好芯片型号和下载方式&#xff0c;再创建一个.asm文件并添加到工程&#xff0c; 工程创建完如图 工程配置 代码 ORG 0000HL…

Ubuntu中 petalinux 安装 移植linux --tftp/tftp-hpa服务的方法

Xilinx 文档 PetaLinux 指南&#xff1a;如何创建 PetaLinux 环境 &#xff08;2019.1&#xff09; PetaLinux工具参考指南 PetaLinux安装详解(Xilinx , linux, zynq, zynqMP) petalinux 2020.1安装教程 一、PetaLinux工具和库安装 PetaLinux 工具要求主机系统 /bin/sh 为“b…

【分享】3种方法取消PPT的“限制保护”

PPT如果设置了有密码的“只读方式”&#xff0c;每次打开PPT&#xff0c;都会出现对话框&#xff0c;提示需要输入密码才能修改文件&#xff0c;否则只能以“只读方式”打开。 以“只读方式”打开的PPT就会被限制&#xff0c;无法进行编辑修改等操作。那如果后续不需要“限制保…

搭建LNMP服务器

一、环境准备 Linux 采用 CentOS7 Nginx 采用 Nginx-1.24.0 安装目录/opt/nginx Mysql 采用 Mysql-5.7.23 安装目录/opt/mysql PHP 采用 PHP-7.3.5 安装目录/opt/php 用于测试环境&#xff0c;搭建在虚拟机上&#xff0c;只准备了一台虚拟机&#xff0c;所有服务都搭建在一…

代码随想录算法训练营第16天 |● 104.二叉树的最大深度 559.n叉树的最大深度 ● 111.二叉树的最小深度 ● 222.完全二叉树的节点个数

文章目录 前言104.二叉树的最大深度思路知识点 方法一 递归法方法二 迭代法 559. n叉树的最大深度111.二叉树的最小深度思路方法一 后向遍历递归法方法二 迭代法 222.完全二叉树的节点个数思路方法一 当成普通二叉树来做方法二 利用完全二叉树的特性 总结 前言 所有的题目一刷…

最简单的,在mac笔记本上安装Unix-v6系统,进行“Unix内核源码剖析”

Unix V6 已经是 1975 年的系统了&#xff0c;但是其源代码拢共只有 1w 行左右&#xff0c;并且使用了 C 语言&#xff08;K & R 之前的标准&#xff09;&#xff0c;还是现代操作系统的鼻祖&#xff0c;所以说是初学者最好的研究对象。 安装模拟器 brew install simh …

U-Mail邮件系统取得多项适配认证,全面支持国产化信创环境

随着信息技术的发展&#xff0c;信息化建设越来越深入到社会各个领域&#xff0c;成为驱动经济社会发展的重要力量。在此背景下&#xff0c;我国正加快构建国家信息安全保障体系&#xff0c;实现自主可控&#xff0c;形成安全可靠的信息技术体系。这正是我们所说的“信创”&…

Mac上安装多版本nodejs 并 随意切换node版本

Mac上安装多版本nodejs 并 随意切换node版本 1. 先查看当前版本2. 说明3. 安装 n 组件4. 根据需要安装其他版本的node4.1 查看node历史版本4.2 安装指定版本的node4.2.1 使用n 组件安装多版本4.2.2 n 组件常用命令 4.3 也可以安装node14 1. 先查看当前版本 如下&#xff1a;no…

26【构图】场景透视 —— 一点透视

1 一点透视更能体现纵深 2 图中的 消失点 透视线 视平线的位置 3 一点透视模型 蓝色的是消失点&#xff0c;根据消失点发射出无数的透视线 在PS中可以用简单的方法画出一点透视的透视线&#xff08;通过多边形工具&#xff09;

电脑视频如何压缩变小 mp4视频太大怎么压缩不影响画质

视频格式是指用于存储、编码、解码和播放数字视频内容的特定文件类型和结构。它定义了视频数据的压缩方式、存储布局以及播放参数&#xff0c;确保不同的设备和软件能够识别并正确处理视频文件。视频格式包括两大部分视频编码格式和容器格式。 视频太大的话有时候上传不了&…

Android Audio基础——AudioFlinger回放录制线程(七)

AndioFlinger 作为 Android 的音频系统引擎,重任之一是负责输入输出流设备的管理及音频流数据的处理传输,这是由回放线程 PlaybackThread 及其派生的子类和录制线程 RecordThread 进行的。 一、基础介绍 1、关系图 ThreadBase:PlaybackThread 和 RecordThread 的基类。 Re…

DDoS攻击的最新动态及市场趋势分析

随着数字化转型的加速和网络连接设备的增加&#xff0c;分布式拒绝服务(Distributed Denial of Service, DDoS)攻击已经成为全球网络安全领域的一大威胁。根据最新的市场研究报告&#xff0c;预计到2028年&#xff0c;DDoS防护软件市场的复合年增长率将达到14%以上&#xff0c;…

工作站虚拟化:RTX A5000的图形工作站实现多用户独立运行Siemens NX 设计软件

一、背景 Siemens NX 是由西门子数字工业软件&#xff08;Siemens Digital Industries Software&#xff09;开发的一款先进的集成计算机辅助设计&#xff08;CAD&#xff09;、计算机辅助制造&#xff08;CAM&#xff09;和计算机辅助工程&#xff08;CAE&#xff09;软件。它…

Linux:Ubuntu修改root密码

Linux&#xff1a;Ubuntu修改root密码 修改默认grub配置文件 rootshanxin:~# vim /etc/default/grub# 主要修改内容如下&#xff1a;GRUB_DEFAULT0 #GRUB_TIMEOUT_STYLEhidden 注释这一行 GRUB_TIMEOUT5 # 将这一行的时间改为5秒进行开启启动的grub文件的复写 rootshanxin:~…

618精选编程书单推荐:优质知识提升你的代码力

前言 在这个快速发展的技术时代&#xff0c;不断学习和提升自己的编程技能是每位程序员的必修课。今天&#xff0c;我为大家精心挑选了一系列编程技术书籍&#xff0c;它们将是你技术成长道路上的宝贵财富。 文章目录 前言编程之路&#xff1a;为何阅读书籍是不可或缺的书籍的…