12. 定时器按键消抖

12. 定时器按键消抖

  • 定时器按键消抖简介
  • 定时器消抖配置步骤
  • 程序编写
    • bsp_keyfilter.h
    • bsp_keyfilter.c
    • main

定时器按键消抖简介

使用延时函数消抖会浪费 CPU 性能,因为延时函数就是空跑。如果按键是使用中断的方式实现的,就更不能在中断服务函数中使用延时函数,因为中断服务函数最基本的要求就是快进快出。 所以可以使用定时器设置好时间,就可以去跑其他的进程,当时间到了,就会触发中断,然后在中断函数中做相应的处理。
在这里插入图片描述
需要在图中t1 ~ t3 这个时间段消抖。设置按键为下降沿触发,因此会在t1、t2和t3这3个时刻会触发按键中断,每次进入中断处理函数都会重新开启定时器中断。但是t1 ~ t2 和 t2 ~ t3 这两个时间段是小于设定的定时器时间,所以虽然 t1 开启了定时器,但是定时器定时器时间还没到,就重置了定时器,最终只有t3时刻开启的定时器能完整的完成整个定时器周期并触发中断

定时器消抖配置步骤

  1. 配置按键 IO 中断
    配置按键所使用的 IO,因为要使用到中断驱动按键,所以要配置 IO 的中断模式
  2. 初始化消抖用的定时器
  3. 编写中断处理函数
    需要两个中断处理函数:按键对应的 GPIO 中断处理函数和 EPIT1 定时器的中断处理函数。按键中断处理函数主要是开启定时器。

程序编写

bsp_keyfilter.h

#pragma once
void filterkey_init();
void filtertimer_init(unsigned int value);
void filtertimer_stop();
void filtertimer_restart(unsigned int value);
void filtertimer_irqhandler();
void gpio1_16_31_irqhandler();

bsp_keyfilter.c

#include "bsp_key.h"
#include "bsp_gpio.h"
#include "bsp_int.h"
#include "bsp_beep.h"
#include "bsp_keyfilter.h"

void fileterkey_init()
{
	gpio_pin_config_t key_config;
	
	// 1. 初始化 IO
	IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
	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);
	
	// 使能 GPIO 中断,并且注册中断处理函数
	GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);
	system_register_irqhandler(GPIO1_Combined_16_31_IRQn,(system_irq_handler_t)gpio1_16_31_irqhandler,NULL);
	gpio_enableint(GPIO1, 18);// 使能GPIO1_IO18中断
	filetertimer_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);	
}

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);	/* 打开定时器 		*/
}

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

void gpio1_16_31_irqhandler(void)
{ 
	// 开启定时器
	filtertimer_restart(66000000/100);
	// 清除中断标志位
	gpio_clearintflags(GPIO1, 18);
}

main

int main(void)
{
	unsigned char state = OFF;

	int_init(); 				// 初始化中断(一定要最先调用)
	imx6u_clkinit();			
	clk_enable();				
	led_init();					
	beep_init();				
	filterkey_init();			

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

	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入浅出Python异常处理 - 你所不知道的Python异常

深入浅出Python异常处理 - 你所不知道的Python异常 前言 在Python编程开发中&#xff0c;异常处理扮演者至关重要的角色。合适的异常处理不仅可以提高代码的健壮性&#xff0c;还能增强程序的可读性和可维护性。在Python编程中&#xff0c;有效地管理异常是提高代码质量的关键…

使用c++解压rar文件,基于UnRAR64,非命令行

最近项目需要解压缩rar文件&#xff0c;我们都知道rar是闭源收费软件&#xff0c;如果直接采用命令行可能会有限制&#xff0c;或者盗版问题&#xff0c;使用正版的winrar命令行解压rar文件是否有限制&#xff0c;这个我没来得及测试&#xff0c;但是从交互体验上来说&#xff…

EFCore: The ConnectionString property has not been initialized.

使用NuGet的程序包管理控制台执行命令“update-database”的时候报出该错误 经过检查发现是optionsBuilder.UseSqlServer(strConn);中的strConn没有写

【python海洋专题四十六】研究区域示意放大图

【python海洋专题四十六】研究区域示意放大图 图片 往期推荐 图片 【python海洋专题一】查看数据nc文件的属性并输出属性到txt文件 【python海洋专题二】读取水深nc文件并水深地形图 【python海洋专题三】图像修饰之画布和坐标轴 【Python海洋专题四】之水深地图图像修饰 …

穿越内存迷宫:C语言地址与指针的的冒险之旅

前言 C语言的魅力在于其直接的内存控制&#xff0c;而地址和指针是这种控制的核心。深入了解这些概念&#xff0c;将帮助我们更好地理解和利用C语言的潜力。本文将带领你踏上地址与指针的奇妙之旅&#xff0c;揭示它们在程序设计中的神秘面纱。 奇妙指针之旅&#xff1a;解码…

日语形容词分类

かっこいい的否定变形是かっこよくない

Selenium自动化测试细节讲解

与以前瀑布式开发模式不同&#xff0c;现在软件测试人员具有使用自动化工具执行测试用例套件的优势&#xff0c;而以前&#xff0c;测试人员习惯于通过测试脚本执行来完成测试。 但自动化测试的目的不是完全摆脱手动测试&#xff0c;而是最大程度地减少手动运行的测试。自动化…

计算机毕业设计选题推荐-农产品销售微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

抖音小程序开发:打造高效餐饮团购平台的技术指南

在餐饮行业&#xff0c;通过抖音小程序开发一个高效的团购平台&#xff0c;可以为餐厅提供更广泛的曝光&#xff0c;增加销售机会。本文将从技术角度出发&#xff0c;为您提供一份详细的抖音小程序开发指南&#xff0c;助您打造一流的餐饮团购平台。 一、确定需求和功能 在开…

让各大运营商都默默流泪的 HTTPS 协议(HTTPS 的加密流程)

文章目录 前言1. 什么是 HTTPS1.1 臭名昭著的 "运营商劫持" 2. 什么是"加密"3. HTTPS 的加密流程3.1 对称加密用对称加密可行吗&#xff1f; 3.2 引入非对称加密用对称加密非对称加密可行吗&#xff1f; 3.3 中间人攻击如何证明浏览器收到的公钥一定是该网…

栈 和 队列

什么是栈? 一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出&#xff08;LIFO - Last In First Out&#xff09;的原则。   从数据结构的角度来看&…

【图文详解】Android Studio(新版本) 配置OpenCV库,解决出现的各种问题

前言 写这篇文章的目的就是记录自己在配置OpenCV库时遇到的问题。在网上查找相关资料时&#xff0c;发现很多Android Studio都是老版本&#xff0c;并且出现的问题都不能被解决。自己在配置过程中出现的问题都进行记录下来并一一解决。 新建项目 点击 New Project 选择界面 …

STM32F4X SDIO(九) 例程讲解-SD卡擦除、读写

STM32F4X SDIO &#xff08;九&#xff09; 例程讲解-SD卡擦除、读写 例程讲解-SD卡擦除、读写SD卡擦除CMD32:ERASE_WR_BLK_START命令发送命令响应 CMD33:ERASE_WR_BLK_END命令发送命令响应CMD38:ERASE命令响应 CMD13:SD_CMD_SEND_STATUS命令发送命令回应 SD卡读数据CMD16:SET_…

【LeetCode】挑战100天 Day10(热题+面试经典150题)

【LeetCode】挑战100天 Day10&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-122.1 题目2.2 题解 三、面试经典 150 题-123.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&…

matplotlib 设置标签和图例

常用标签 xlabel&#xff1a;x轴标签名称。 ylabel&#xff1a;y轴标签名称。 title&#xff1a;图像标题。 设置x和y轴的刻度&#xff1a;xticks和yticks。 nums np.arange(0, 1.3, 0.01)# 设置标题 plt.title("title") # 设置横坐标信息 plt.xlabel("x-…

复杂度计算实例

1.常见时间复杂度计算举例 实例1 实例1基本操作执行了2N10次&#xff0c;通过推导大O阶方法知道&#xff0c;时间复杂度为 O(N) 实例2 实例2基本操作执行了MN次&#xff0c;有两个未知数M和N&#xff0c;时间复杂度为 O(NM) 实例3 实例3基本操作执行了100次&#xff0c;通过…

C++学习笔记(二):C++是如何运行的

C是如何运行的 include 预处理语句&#xff0c;在编译前就会被处理。 main函数 程序入口。 #include <iostream>int main() {std::cout << "Hello World!" << std::endl;std::cin.get();return 0; }Visual Studio 解决方案平台指的是编译的代码的…

探索微信小程序框架的精华——高质量的优秀选择

目录 引言&#xff1a; 1. 框架性能 2. 开发者工具支持 3. 文档和社区支持 4. 扩展能力 5. 使用率和稳定性 结语&#xff1a; 引言&#xff1a; 微信小程序作为一种轻量级、高效便捷的应用形式&#xff0c;已经在移动应用领域占据了重要地位。而其中&#xff0c;选择一个…

Nussbaumer Transform 以及 Amortized FHEW bootstrapping

参考文献&#xff1a; [Nuss80] Nussbaumer H. Fast polynomial transform methods for multidimensional DFTs[C]//ICASSP’80. IEEE International Conference on Acoustics, Speech, and Signal Processing. IEEE, 1980, 5: 235-237.[SV11] Smart N P, Vercauteren F. Full…

C++ 配合图形库实现画线效果

#include<stdio.h> #include <conio.h> #include<math.h> #include <graphics.h> // 引用图形库头文件 #define N 12 int List[N][N];void draw() {for (int i 0; i < N; i) {int x 200 * cos(2 * 3.14 * i / N);int y 200 * sin(2 * 3.1…