【Linux 裸机篇(八)】I.MX6U EPIT 定时器中断、定时器按键消抖
目录
- 一、EPIT 定时器简介
- 二、定时器按键消抖
一、EPIT 定时器简介
EPIT 的全称是: Enhanced Periodic Interrupt Timer,直译过来就是增强的周期中断定时器,它主要是完成周期性中断定时的。学过 STM32 的话应该知道, STM32 里面的定时器还有很多其它的功能,比如输入捕获、 PWM 输出等等。但是 I.MX6U 的 EPIT 定时器只是完成周期性中断定时的,仅此一项功能!至于输入捕获、 PWM 输出等这些功能, I.MX6U由其它的外设来完成。
EPIT 是一个 32 位定时器,在处理器几乎不用介入的情况下提供精准的定时中断,软件使能以后 EPIT 就会开始运行, EPIT 定时器有如下特点:
①:时钟源可选的 32 位向下计数器。
②:12 位的分频值。
③:当计数值和比较值相等的时候产生中断。
EPIT 定时器结构如图所示:

图中各部分的功能如下:
①:这是个多路选择器,用来选择 EPIT 定时器的时钟源, EPIT 共有 3 个时钟源可选择,ipg_clk、 ipg_clk_32k 和 ipg_clk_highfreq。
②:这是一个 12 位的分频器,负责对时钟源进行分频, 12 位对应的值是 0~4095,对应着 1~4096 分频。
③:经过分频的时钟进入到 EPIT 内部,在 EPIT 内部有三个重要的寄存器:计数寄存器(EPIT_CNR)、加载寄存器(EPIT_LR)和比较寄存器(EPIT_CMPR),这三个寄存器都是 32 位的。EPIT 是一个向下计数器,也就是说给它一个初值,它就会从这个给定的初值开始递减,直到减为 0,计数寄存器里面保存的就是当前的计数值。如果 EPIT 工作在 set-and-forget 模式下,当计数寄存器里面的值减少到 0, EPIT 就会重新从加载寄存器读取数值到计数寄存器里面,重新开始向下计数。比较寄存器里面保存的数值用于和计数寄存器里面的计数值比较,如果相等的话就会产生一个比较事件。
④:比较器。
⑤:EPIT 可以设置引脚输出,如果设置了的话就会通过指定的引脚输出信号。
⑥:产生比较中断,也就是定时中断。
EPIT 定时器有两种工作模式: set-and-forget 和 free-running,这两个工作模式的区别如下:
set-and-forget 模式:EPITx_CR(x=1, 2)寄存器的 RLD 位置 1 的时候 EPIT 工作在此模式下,在此模式下 EPIT 的计数器从加载寄存器 EPITx_LR 中获取初始值,不能直接向计数器寄存器写入数据。不管什么时候,只要计数器计数到 0,那么就会从加载寄存器 EPITx_LR 中重新加载数据到计数器中,周而复始。
free-running 模式: EPITx_CR 寄存器的 RLD 位清零的时候 EPIT 工作在此模式下,当计数器计数到0以后会重新从0XFFFFFFFF开始计数,并不是从加载寄存器 EPITx_LR中获取数据。
接下来看一下 EPIT 重要的几个寄存器,第一个就是 EPIT 的配置寄存器 EPITx_CR,此寄存器的结构如图所示:


寄存器 EPITx_SR 结构体如图所示:


EPIT 的配置步骤如下:

程序编写
#ifndef _BSP_EXIT_H
#define _BSP_EXIT_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_exit.h
作者 : 左忠凯
版本 : V1.0
描述 : 外部中断驱动头文件。
其他 : 配置按键对应的GPIP为中断模式
论坛 : www.wtmembed.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "imx6ul.h"/* 函数声明 */
void exit_init(void); /* 中断初始化 */
void gpio1_io18_irqhandler(void); /* 中断处理函数 */#endif
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_exit.c
作者 : 左忠凯
版本 : V1.0
描述 : 外部中断驱动。
其他 : 配置按键对应的GPIP为中断模式
论坛 : www.wtmembed.com
日志 : 初版V1.0 2019/1/4 左忠凯创建
***************************************************************/
#include "bsp_exit.h"
#include "bsp_gpio.h"
#include "bsp_int.h"
#include "bsp_delay.h"
#include "bsp_beep.h"/** @description : 初始化外部中断* @param : 无* @return : 无*/
void exit_init(void)
{gpio_pin_config_t key_config;/* 1、设置IO复用 */IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0); /* 复用为GPIO1_IO18 */IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);/* 2、初始化GPIO为中断模式 */key_config.direction = kGPIO_DigitalInput;key_config.interruptMode = kGPIO_IntFallingEdge;key_config.outputLogic = 1;gpio_init(GPIO1, 18, &key_config);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); /* 使能GIC中对应的中断 */system_register_irqhandler(GPIO1_Combined_16_31_IRQn, (system_irq_handler_t)gpio1_io18_irqhandler, NULL); /* 注册中断服务函数 */gpio_enableint(GPIO1, 18); /* 使能GPIO1_IO18的中断功能 */
}/** @description : GPIO1_IO18最终的中断处理函数* @param : 无* @return : 无*/
void gpio1_io18_irqhandler(void)
{ static unsigned char state = 0;/**采用延时消抖,中断服务函数中禁止使用延时函数!因为中断服务需要*快进快出!!这里为了演示所以采用了延时函数进行消抖,后面我们会讲解*定时器中断消抖法!!!*/delay(10);if(gpio_pinread(GPIO1, 18) == 0) /* 按键按下了 */{state = !state;beep_switch(state);}gpio_clearintflags(GPIO1, 18); /* 清除中断标志位 */
}
二、定时器按键消抖
按键消抖的原理就是在按键按下以后延时一段时间再去读取按键值,如果此时按键值还有效那就表示这是一次有效的按键,中间的延时就是消抖的。但是这有一个缺点,就是延时函数会浪费 CPU 性能,因为延时函数就是空跑。如果按键是用中断方式实现的,那就更不能在中断服务函数里面使用延时函数,因为中断服务函数最基本的要求就是快进快出!上一章我们学习了 EPIT 定时器,定时器设置好定时时间,然后 CPU 就可以做其他事情去了,定时时间到了以后就会触发中断,然后在中断中做相应的处理即可。因此,我们可以借助定时器来实现消抖,按键采用中断驱动方式,当按键按下以后触发按键中断,在按键中断中开启一个定时器,定时周期为 10ms,当定时时间到了以后就会触发定时器中断,最后在定时器中断处理函数中读取按键的值,如果按键值还是按下状态那就表示这是一次有效的按键。定时器按键消抖如图所示:

图中 t1~t3 这一段时间就是按键抖动,是需要消除的。设置按键为下降沿触发,因此会在 t1、 t2 和 t3 这三个时刻会触发按键中断,每次进入中断处理函数都会重新开器定时器中断,所以会在 t1、 t2 和 t3 这三个时刻开器定时器中断。但是 t1~t2 和 t2~t3 这两个时间段是小于我们设置的定时器中断周期(也就是消抖时间,比如 10ms),所以虽然 t1 开启了定时器,但是定时器定时时间还没到呢 t2 时刻就重置了定时器,最终只有 t3 时刻开启的定时器能完整的完成整个定时周期并触发中断,我们就可以在中断处理函数里面做按键处理了,这就是定时器实现按键防抖的原理, Linux 里面的按键驱动用的就是这个原理!
关于定时器按键消抖的原理就介绍到这里,接下来讲解如何使用 EPIT1 来配合按键 KEY来实现具体的消抖,步骤如下:

程序编写
#ifndef _BSP_KEYFILTER_H
#define _BSP_KEYFILTER_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_keyfilter.h
作者 : 左忠凯
版本 : V1.0
描述 : 定时器按键消抖驱动头文件。
其他 : 无
论坛 : www.wtmembed.com
日志 : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************//* 函数声明 */
void filterkey_init(void);
void filtertimer_init(unsigned int value);
void filtertimer_stop(void);
void filtertimer_restart(unsigned int value);
void filtertimer_irqhandler(void);
void gpio1_16_31_irqhandler(void);#endif
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_keyfilter.c
作者 : 左忠凯
版本 : V1.0
描述 : 定时器按键消抖驱动。
其他 : 按键采用中断方式,按下按键触发按键中断,在按键中断里面使能定时器定时中断。使用定时器定时中断来完成消抖延时,定时器中断周期就是延时时间。如果定时器定时中断触发,表示消抖完成(延时周期完成),即可执行按键处理函数。
论坛 : www.wtmembed.com
日志 : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************/
#include "bsp_key.h"
#include "bsp_gpio.h"
#include "bsp_int.h"
#include "bsp_beep.h"
#include "bsp_keyfilter.h"/** @description : 按键初始化* @param : 无* @return : 无*/
void filterkey_init(void)
{ gpio_pin_config_t key_config;/* 1、初始化IO复用 */IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0); /* 复用为GPIO1_IO18 *//* 2、、配置GPIO1_IO18的IO属性 *bit 16:0 HYS关闭*bit [15:14]: 11 默认22K上拉*bit [13]: 1 pull功能*bit [12]: 1 pull/keeper使能*bit [11]: 0 关闭开路输出*bit [7:6]: 10 速度100Mhz*bit [5:3]: 000 关闭输出*bit [0]: 0 低转换率*/IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);/* 3、初始化GPIO为中断 */key_config.direction = kGPIO_DigitalInput;key_config.interruptMode = kGPIO_IntFallingEdge;key_config.outputLogic = 1;gpio_init(GPIO1, 18, &key_config);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); /* 使能GIC中对应的中断 *//* 注册中断服务函数 */system_register_irqhandler(GPIO1_Combined_16_31_IRQn, (system_irq_handler_t)gpio1_16_31_irqhandler, NULL);gpio_enableint(GPIO1, 18); /* 使能GPIO1_IO18的中断功能 */filtertimer_init(66000000/100); /* 初始化定时器,10ms */
}/** @description : 初始化用于消抖的定时器,默认关闭定时器* @param - value : 定时器EPIT计数值* @return : 无*/
void filtertimer_init(unsigned int value)
{EPIT1->CR = 0; //先清零/** CR寄存器:* bit25:24 01 时钟源选择Peripheral clock=66MHz* bit15:4 0 1分频* bit3: 1 当计数器到0的话从LR重新加载数值* bit2: 1 比较中断使能* bit1: 1 初始计数值来源于LR寄存器值* bit0: 0 先关闭EPIT1*/EPIT1->CR = (1<<24 | 1<<3 | 1<<2 | 1<<1);/* 计数值 */EPIT1->LR = value;/* 比较寄存器,当计数器值和此寄存器值相等的话就会产生中断 */EPIT1->CMPR = 0; GIC_EnableIRQ(EPIT1_IRQn); /* 使能GIC中对应的中断 *//* 注册中断服务函数 */system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)filtertimer_irqhandler, NULL);
}/** @description : 关闭定时器* @param : 无* @return : 无*/
void filtertimer_stop(void)
{EPIT1->CR &= ~(1<<0); /* 关闭定时器 */
}/** @description : 重启定时器* @param - value : 定时器EPIT计数值* @return : 无*/
void filtertimer_restart(unsigned int value)
{EPIT1->CR &= ~(1<<0); /* 先关闭定时器 */EPIT1->LR = value; /* 计数值 */EPIT1->CR |= (1<<0); /* 打开定时器 */
}/** @description : 定时器中断处理函数 * @param : 无* @return : 无*/
void filtertimer_irqhandler(void)
{ static unsigned char state = OFF;if(EPIT1->SR & (1<<0)) /* 判断比较事件是否发生 */{filtertimer_stop(); /* 关闭定时器 */if(gpio_pinread(GPIO1, 18) == 0) /* KEY0 */{state = !state;beep_switch(state); /* 反转蜂鸣器 */}}EPIT1->SR |= 1<<0; /* 清除中断标志位 */
}/** @description : GPIO中断处理函数* @param : 无* @return : 无*/
void gpio1_16_31_irqhandler(void)
{ /* 开启定时器 */filtertimer_restart(66000000/100);/* 清除中断标志位 */gpio_clearintflags(GPIO1, 18);
}
相关文章:
【Linux 裸机篇(八)】I.MX6U EPIT 定时器中断、定时器按键消抖
目录 一、EPIT 定时器简介二、定时器按键消抖 一、EPIT 定时器简介 EPIT 的全称是: Enhanced Periodic Interrupt Timer,直译过来就是增强的周期中断定时器,它主要是完成周期性中断定时的。学过 STM32 的话应该知道, STM32 里面的…...
Web安全 XSS靶场搭建(玩转整个XSS环境.)
Web安全 XSS靶场搭建 XSS又叫CSS(Cross Site Script)跨站脚本攻击,指的是攻击者在Web页面,插入恶意JS代码,当用户浏览该页之时,嵌入其中JS代码就会被执行,从而达到攻击的目的.(包含…...
前端开发技术——DOM(上)
一.单选题(共4题,44.4分) 1 下列选项中,关于事件的描述错误的是() A、 事件指的是可以被JavaScript侦测到的行为 B、 事件驱动程序指的是事件触发后要执行的代码 C、 事件源是指触发的事件 D、 事件的种类称为事件…...
银河麒麟v10服务器版安装OpenDDS
1. OpenDDS简介 OpenDDS是OMG数据分发服务(DDS)的一种开源实现,它遵循实时系统v1.2的DDS规范(OMG Document formal/07-01-01)和实时公布/订阅互操作性通信协议v2.1的DDS-RTPS规范(OMG Document formal/2010-11-01)。OpenDDS由OCI公司设计和维护,可从http…...
curl方式调用电商API接口示例 详细介绍
cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。 cURL支持的通信协议有FTP、FTPS、HTTP、H…...
Duboo介绍与入门
文章目录 1、Dubbo的前世今生2、Dubbo的快速入门2.1、Dubbo的基本架构2.2、Nacos2.3、管理后台2.4、入门案例2.4.1、服务提供者搭建环境代码实现配置文件 2.4.2、服务消费者搭建环境代码实现配置文件 最后说一句 1、Dubbo的前世今生 2011年10月27日,阿里巴巴开源了…...
人工智能中(Pytorch)框架下模型训练效果的提升方法
大家好,我是微学AI,今天给大家介绍一下人工智能中(Pytorch)框架下模型训练效果的提升方法。随着深度学习技术的快速发展,越来越多的应用场景需要建立复杂的、高精度的深度学习模型。为了实现这些目标,必须采用一系列复杂的技术来提…...
树莓派CSI摄像头使用python调用opencv库函数进行运动检测识别
目录 一、完成摄像头的调用 二、利用python调用opencv库函数对图像进行处理 2.1 图像处理大体流程 2.2 opencv调用函数的参数以及含义 2.2.1 ret, img cap.read() 读取帧图像 2.2.2 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 灰度图像 2.2.3 gray_diff_img cv2.absdiff(g…...
Parameters(in)、Parameters(out) and Parameters(inout)
0前言 参数类型(Parameters)指的是函数参数在调用时所具有的性质,从而对函数的调用方式产生影响。在 C 语言中,存在三种不同类型的函数参数:Parameters(in)、Parameters(out) 和 Parameters(inout) 1定义 Parameter…...
jstat命令查看jvm内存情况及GC内存变化
命令格式 jstat [Options] pid [interval] [count] 参数说明: Options,选项,一般使用 -gc、-gccapacity查看gc情况 pid,VM的进程号,即当前运行的java进程号 interval,间隔时间(按该时间频率自动刷新当前内存…...
java 图形化小工具Abstract Window Toolit :画笔Graphics,画布Canvas(),弹球小游戏
画笔Graphics Java中提供了Graphics类,他是一个抽象的画笔,可以在Canvas组件(画布)上绘制丰富多彩的几何图和位图。 Graphics常用的画图方法如下: drawLine(): 绘制直线drawString(): 绘制字符串drawRect(): 绘制矩形drawRoundRect(): 绘制…...
HCIA-RS实验-STP和RSTP(1)
这篇文章开始前,先简单说下这2个协议; 本文介绍了STP和RSTP的基本原理、优缺点以及应用场景。STP和RSTP都是生成树协议,主要作用于避免网络中的环路,保证数据包能够正常转发。在实际应用中,需要根据实际情况选择合适的…...
Leetcodes刷题之删除链表的倒数N个结点和删除链表的中间的结点
吾心信其可行,则移山填海之难,终有成功之日。 --孙中山 目录 🍉一.删除链表的倒数N个结点 🌻1.双指针 🍁2.求链表的长度 🌸二.删除链表的中间的结点 🍉一.删除链…...
Java-数据结构-并查集<二>
一.并查集的简单介绍 二. 并查集的主要构成和实现方式 三.HashMap模板和数组模板 由于在下文的模板基本一致,不再每次都罗列,大体的模板如下,若有错误可以在leetcode找到对应的题目解答,已经附上连接。 HashMap class UnionFi…...
JSP网上教学资源共享系统(源代码+论文)
通过网上教学资源共享系统的建设,完成了对于操作系统课程的远程化授课。可以使学生不受时间空间的限制,通过网络对于这门课程进行学习。建立起了基于B/C的网络化教学系统。本网站采用当前最流行的JSP网络编程技术,可以实现数据的高效、动态、…...
QT C++入门学习(1) QT Creator安装和使用
Qt官方下载 Qt 官网有一个专门的资源下载网站,所有的开发环境和相关工具都可以从这里下载,具体地址是:http://download.qt.io/ 进入链接后,是一个文件目录,依次进入这个路径:archive/qt/5.12/5.12.9/qt-o…...
UE动画状态机的事件触发顺序测试
正常A状态过渡到B状态的事件顺序: 整个流程为: 调用B状态的On Become Relevant事件调用B状态的On Update事件调用A状态的Left State Event事件调用B状态的Entered State Event事件调用B状态的Start Transition Event事件调用B状态的End Transition Even…...
数学建模的搜索技巧
你真的会使用“度娘”吗?是不是在查找所需要的东西的时候,搜出来的信息价值并不是很大,跟着北海老师学习,如何更高效的使用百度去查询自己想要的,有用的资料! 搜索技巧 完全匹配搜索 : 查询词的外边加上双…...
学成在线笔记+踩坑(10)——课程搜索、课程发布时同步索引库。
导航: 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题_java黑马笔记 目录 1 【检索模块】需求分析 1.1 全文检索介绍 1.2 业务流程 1.2.1、课程发布时索引库里新增一条记录 1.2.2、课程搜索 2 准…...
某应用虚拟化系统远程代码执行
漏洞简介 微步在线漏洞团队通过“X漏洞奖励计划”获取到瑞友天翼应用虚拟化系统远程代码执行漏洞情报(0day),攻击者可以通过该漏洞执行任意代码,导致系统被攻击与控制。瑞友天翼应用虚拟化系统是基于服务器计算架构的应用虚拟化平台,它将用户…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
