i.MX6ULL(七) 按键抖动消除

按键消抖&蜂鸣器 由于按键的物理特性,芯片会识别信号出现多次高低电平变化,会出现如下图的未消抖信号。影响我们的整个项目。所以我们在使用按键时需要消抖,以确保按键被按下时只检测到一次低电平,我们期望的效果如下。根据延时计数器获取状态(是否抖动)的按键信号。 阅读详情

1 按键消抖的原理

 其实就是在按键按下以后延时一段时间再 去读取按键值,如果此时按键值还有效那就表示这是一次有效的按键,中间的延时就是消抖的。

延时函数实现 会浪费 CPU 性能,因为延时函数就是空跑。

我们可以借助定时器来实现消抖,按键采用中断驱动方式,

当按键按下以后触发按键中断,在 按键中断中开启一个定时器,定时周期为 10ms,当定时时间到了以后就会触发定时器中断,最 后在定时器中断处理函数中读取按键的值,如果按键值还是按下状态那就表示这是一次有效的 按键。定时器按键消抖如图 19.1.1 所示:

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

2 编写驱动代码

        整合按键中断及EPTI定时器中断,按键中断服务函数内开启EPTI定时器中断 ,下一步,将按键中断中的延迟函数 通过EPTI定时器触发 在服务函数中检查电平输出值 ,按键按下 触发蜂鸣器 ,关闭EPTI定时器中断 按键中断标志位 

  1.  初始化IO 按键 GPIO)IOMUXC_UART1_CTS_B_GPIO1_IO18
  2. 初始化GPIO为中断
  3. 使能 GPIO 中断,并且注册中断处理函数 gpio1_16_31_irqhandler
  4. 初始化EPTI1定时器 并且注册中断处理函数   filtertimer_irqhandler
  5. 按键中断服务函数 gpio1_16_31_irqhandler 开启定时器  清除中断标志  图 5-1 
  6. filtertimer_irqhandler 关闭 filtertimer_stop 定时器读取按键引脚电平 清除定时器中断标志位 图 6-1 

图 5-1 

void gpio1_16_31_irqhandler(void)

{

    /* 开启定时器 */

    filtertimer_restart(66000000/100);

    /* 清除中断标志位 */

    gpio_clearintflags(GPIO1, 18);

}

图 6-1 

/*
 * @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;                         /* 清除中断标志位                 */
}

完整代码  bsp_keyfilter.c

/***************************************************************
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);
}

main函数 后续代码逻辑同通用BSP 业务处理流程

/*
 * @description	: main函数
 * @param 		: 无
 * @return 		: 无
 */
int main(void)
{
	unsigned char state = OFF;

	int_init(); 				/* 初始化中断(一定要最先调用!) */
	imx6u_clkinit();			/* 初始化系统时钟 			*/
	clk_enable();				/* 使能所有的时钟 			*/
	led_init();					/* 初始化led 			*/
	beep_init();				/* 初始化beep	 		*/
	filterkey_init();			/* 带有消抖功能的按键 */

	while(1)			
	{	
		state = !state;
		led_switch(LED0, state);
		delay(500);
	}

	return 0;
}

I.MX6ULL ARM驱动开发---Linux内核定时器 阅读详情

相关推荐

i.MX6ULL终结者开发板:从原理图到实战,手把手教你读懂30个核心电路模块

本文深入解析i.MX6ULL终结者开发板的30个核心电路模块,从原理图分析到底板设计,手把手教你掌握硬件设计的工程智慧。涵盖电源架构、通信接口、人机交互等关键电路,提供实战代码示例和调试技巧,助力开发者快速实现工业级应用。

weixin_30379531的博客 505

按键消抖记录

按键消抖

Li_Lei1的博客 1780

I.MX6ULL硬件设计避坑指南:那些数据手册没明说的GPIO配置细节

本文深入解析I.MX6ULL硬件设计中GPIO配置的关键细节,包括迟滞使能(HYS)、开漏模式(ODE)与上拉电阻的匹配、驱动强度(DSE)与EMI的平衡等。通过实测数据和案例分析,帮助工程师避开常见设计陷阱,提升信号完整性和系统稳定性。特别适合从STM32转向I.MX6ULL的开发者参考。

weixin_30664051的博客 368

按键消抖、长按的处理方案(中断法、延时法)

以上代码,基本逻辑就是设置一个10ms的定时中断,在中断扫描按键。按键的消抖、按下、松开、长按都可以在中断中快速检测,不会有延时函数长时间占用CPU。在中断中将标志位置一,在主循环中执行处理函数,避免因执行处理函数,占用中断过长时间。以上的代码可以起到良好的消抖作用,在一些小项目的经常运用。但是由于该方式,在消抖延时期间和松手判断期间都会长时间占用CPU,有可能影响其他功能,对系统的实时性造成影响。如果程序不采取一些算法进行消抖,会出现一次按下,多次检测到按键的情况,造成识别异常。

u012500747的博客 6919

告别玄学:手把手教你配置I.MX6ULL的Boot引脚和eFuse,让开发板上电就跑

本文详细解析了I.MX6ULL开发板的启动配置,包括Boot引脚设置、eFuse编程和镜像构建。通过实战案例和避坑指南,帮助开发者快速解决启动失败问题,确保开发板上电即运行。重点介绍了Boot模式选择、存储介质配置及熔丝烧写等关键步骤。

weixin_28707739的博客 205

基于pjsip的VoIP语音通话实战案例:从零实现完整示例

手把手带你用pjsip实现VoIP语音通话,涵盖环境搭建、SIP注册、呼叫控制与媒体传输全流程。深入剖析pjsip核心API调用逻辑,结合真实网络场景调试技巧,助你快速掌握跨平台实时音视频通信开发要领。

weixin_33750664的博客 303

I.MX6ULL 定时器按键消抖实验

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

Redhat_yan 1229

嵌入式Linux串口与RS485驱动开发实战指南

串口通信作为嵌入式系统的核心基础技术,通过UART协议实现设备间可靠数据传输。其工作原理基于起始位、数据位和停止位的帧结构,支持从9600bps到1.5Mbps的波特率范围。在工业物联网和智能家居领域,RS485总线凭借差分传输特性,可实现1200米远距离通信和32节点组网能力。本文以I.MX6ULL平台为例,详细解析Linux内核串口驱动框架,涵盖设备树配置、DMA优化和Modbus协议栈实现等关键技术,特别针对工业现场常见的信号干扰、总线冲突等问题提供实测解决方案。通过开发板上的CH340C和SP348

hqmln的博客 472

【i.MX6ULL】驱动开发8——中断法检测按键

上篇,学习GPIO输入功能的使用,本篇,来学习使用中断的方式来检测按键的按下。 文章目录1 Linux中断介绍1.1 中断的上半部与下半部1.2 下半部的3种实现方式1.2.1 软中断1.2.2 tasklet1.2.3 工作队列1.3 中断API函数1.3.1 request_irq中断请求函数1.3.2 free_irq中断释放函数1.3.3 irq_handler_t中断处理函数1.3.4 中断使能/禁用函数1.3.5 获取中断号2 软件编写2.1 修改设备树文件2.2 按键中断驱动程序2.2.1 硬

码农爱学习的博客 2085

嵌入式Linux触摸屏开发避坑指南:tslib 1.16从源码编译到Qt应用实战

本文详细解析了嵌入式Linux触摸屏开发中tslib 1.16的深度优化与Qt集成全流程。从源码编译、系统集成到性能调优,提供了针对i.MX6ULL、RK3288等开发板的实战指南,帮助开发者解决触摸延迟、坐标校准等核心问题,实现工业级触摸交互体验。

weixin_30411819的博客 189

按键检测代码,采用delay_ms方式,进行延时防抖。优点是不需要等到按键弹起就可以检测,缺点是会产生delay阻塞。

1.内容概要: 按键检测代码,采用delay_ms方式,进行延时防抖。优点是不需要等到按键弹起就可以检测,缺点是会产生delay阻塞。 2. 使用说明: 通过修改宏定义可以修改开关时间; 通过查看头文件可以方便移植到不同硬件上; 3. 适合人群: 适合STM32学习者,或者STM32从业人员,便于积累功能模块,了解无阻塞设计方式;掌握静态全局变量,全局变量使用方法 4. 其他说明: 详情见博客: http://t.csdn.cn/DP43e

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-13-按键实验

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

小狗爱吃黄桃罐头的博客 744

Hcaptcha验证码的‘免浏览器’破解思路:协议分析与N值算法逆向

本文深入解析Hcaptcha验证码的‘免浏览器’破解思路,通过协议分析与N值算法逆向,实现高效自动识别。文章详细拆解Hcaptcha的API交互流程,揭示关键参数`req`和`n`的生成机制,并提供轻量级实现方案,显著降低资源消耗,适用于大规模数据采集等场景。

weixin_30838873的博客 535

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

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

小狗爱吃黄桃罐头的博客 481

HRnet的pytorch实现

HRnet的pytorch实现

奋土的博客 1953

Dify实战应用指南(上传需求稿生成测试用例)

摘要: Dify是一款开源大语言模型应用开发平台,通过低代码/无代码方式支持AI应用开发。平台提供五种核心应用类型,包括聊天助手、文本生成、Agent、ChatFlow和Workflow,适用于不同场景。本文以ChatFlow为例,演示如何上传需求稿自动生成测试用例。通过条件分支、文档提取器和LLM设置,实现从需求文档到测试用例的自动化转换,显著提升测试效率并降低人工误差。该方案适用于需要快速生成测试用例的软件开发场景,尤其适合非技术人员使用。

Linda的自动化测试之旅 2744

11_I.MX6ULL定时器按键消抖

定时器按键消抖简介定时器按键消抖简介其实就是在按键按下以后延时一段时间再去读取按键值,如果此时按键值还有效那就表示这是一次有效的按键,中间的延时就是消抖的。但是这有一个缺点,就是延时函数会浪费CPU性能,因为延时函数就是空跑。如果按键是用中断方式实现的,那就更不能在中断服务函数里面使用延时函数,因为中断服务函数最基本的要求就是快进快出!EPIT定时器,定时器设置好定时时间,然后CPU就可以做其他事情去了,定时时间到了以后就会触发中断,然后在中断中做相应的处理即可。

Yuanghxb的博客 377

ArduPilot移植到自定义硬件:完整指南

详解如何将ArduPilot成功移植到自定义硬件平台,涵盖环境搭建、代码配置与调试技巧。无论是初学者还是进阶开发者,都能快速掌握ArduPilot在不同硬件上的适配方法,提升开发效率。

weixin_28931449的博客 639

i.MX6ULL终结者定时器按键原理及原理分析

1 定时器按键原理 按键消除抖动的原理在前面章节已经介绍了,其实就是按键按下以后延时一段时间在去读按键的状态,如果此时按键还是按下的状态,就说明这是一次有效的按键,延时的时间段就是消除抖动的。上一章我们学习了EPIT定时器,可以知道定时器的工作不受CPU的干预,只要cpu设置好定时时间,定时器就会自己工作,CPU同时去做其它事情,时间到了以后定时器会产生中断通知CPU,然后CPU才会停下当前的事情,去中断处理函数中处理定时器指定的任务,处理完指定的任务,CPU返回到中断前处理的事情上面,继续处理中断发生前的

weixin_46635880的博客 285

【经验分享】使用Keil5烧录代码遇到的问题及解决方法

本文介绍了在使用Keil5烧录代码过程中可能遇到的常见问题,主要为编译错误和下载失败,并提供了解决方案和注意事项。通过本文中提供的具体解决方案和注意事项,希望能够帮助读者更加顺利地进行Keil5烧录代码操作,提高开发效率和成果实现。

qq_63195670的博客 1万+

【OpenClaw从入门到精通】第37篇:教育“龙虾”进化论——从答疑助教到全流程智能教学系统(2026实测版)

2026年,教育AI已从被动答疑的L1级进化至主动教学的L4级,清华开源的OpenMAIC平台更是打破传统慕课局限,实现互动式AI课堂。本文基于天津工业大学、西北农林科技大学等高校的真实应用案例,结合腾讯云、天翼云的实操指南,详解OpenClaw在教育场景的四层进化路径。核心内容包括:L1-L4级教育自动化架构解析、清华OpenMAIC L4级AI课堂深度拆解、从零搭建智能答疑(QQ群机器人)+作业批改+学情分析全流程系统,以及高校网络安全合规部署方案。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 795

imx6ull_GPIO控制LED灯

GPIO 通用输入/输出外设提供专用的通用管脚,可以配置为输入或输出。当配置为输出时,可以写入内部寄存器以控制管脚的电平状态。当配置为输入时,可以通过向其内部寄存器写值来控制管脚输出的电平状态。此外,GPIOperipheral 可以产生CORE 中断。GPIO 是控制芯片 IOMUX 的模块之一。IO管脚复用功能配置IO管脚复用功能配置寄存器IO管脚复用功能配置内部结构。

qq_58395220的博客 1713

新能源汽车电机交流电流测量系统精度全链路分析

通过全链路误差建模与瓶颈分析,结合硬件选型优化与软件算法补偿,可将系统精度从4.2%提升至≤1% FS。本文所述方法论已应用于某800V电驱平台开发,实测电流控制精度达±0.8%,为高性能电机控制奠定基础。为例,深入剖析从互感器采集到CAN报文解析的全链路信号处理流程,揭示各环节误差来源及对最终精度的影响,为研发测试提供理论支撑。:±0.1%(电阻温漂与运放开环增益限制):运放增益带宽积(GBW)不足导致高频衰减。:±0.02%/℃(铁氧体材料温敏特性):±0.5%读数(磁芯饱和效应)

优快云-新能源汽车研发测试专业博主 1493

超越数据表:深入ADC的校准与误差补偿实战

本文深入探讨ADC校准与误差补偿的实战技术,涵盖偏移/增益校准、温度补偿策略及i.MX6ULL硬件特性应用。通过多项式拟合、自适应滤波等高级算法,有效提升ADC在复杂环境下的测量精度,为嵌入式系统提供从硬件到软件的系统级解决方案。

vvv99的博客 740

27、超声成像技术与原理全面解析

本博客全面解析了超声成像技术与原理,涵盖声学材料特性、超声成像系统的基本概念与组成、关键技术如多普勒和聚焦技术、超声换能器的设计与原理、图像处理方法、系统校准与质量控制,以及超声成像的应用领域和发展趋势。旨在为医学诊断、工业检测和海洋声学等领域的研究人员和工程师提供深入的技术参考和指导。

z2a3b4c5d的博客 494

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

音诺ai翻译机集成Realtek RTL8211F实现百兆网口高速接入

音诺AI翻译机集成Realtek RTL8211F百兆以太网PHY芯片,通过有线连接实现低延迟、高可靠网络接入。该方案提升语音传输稳定性,支持远程升级、同传等关键场景,并在硬件设计、接口选型与系统驱动方面优化布局,确保复杂环境下持续稳定运行。

weixin_30923011的博客 730

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

上一篇: i.MX6ULL(六) EPIT定时器
下一篇: MIPI
江太翁
博客等级 码龄15年 271粉丝 141原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值