按键消抖实验
1. 步骤
1、配置按键 IO 中断
配置按键所使用的 IO,因为要使用到中断驱动按键,所以要配置 IO 的中断模式。
2、初始化消抖用的定时器
上面已经讲的很清楚了,消抖要用定时器来完成,所以需要初始化一个定时器,这里使用
上一章讲解的 EPIT1 定时器,也算是对 EPIT1 定时器的一次巩固。定时器的定时周期为 10ms,也可根据实际情况调整定时周期。
3、编写中断处理函数
需要编写两个中断处理函数:按键对应的 GPIO 中断处理函数和 EPIT1 定时器的中断处理
函数。在按键的中断处理函数中主要用于开启 EPIT1 定时器,EPIT1 的中断处理函数才是重点,按键要做的具体任务都是在定时器 EPIT1 的中断处理函数中完成的,比如控制蜂鸣器打开或关闭。
2. 代码
keyfilter.h
#ifndef __BSP_KEYFILTER
#define __BSP_KEYFILTER
#include "imx6ul.h"
/* 函数声明 */
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 // !__BSP_KEYFILTER
keyfilter.c
#include "bsp_keyfilter.h"
#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);
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);
/* 3、 使能 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 的中断功能 */
filtertimer_init(66000000/100); /* 初始化定时器,10ms */
}
/*
* @description : 初始化用于消抖的定时器,默认关闭定时器
* @param - value : 定时器 EPIT 计数值
* @return : 无
*/
void filtertimer_init(unsigned int value)
{
EPIT1->CR = 0; /* 先清零 */
EPIT1->CR = (1<<24 | 1<<3 | 1<<2 | 1<<1);
EPIT1->LR = value; /* 计数值 */
EPIT1->CMPR = 0; /* 比较寄存器为 0 */
/* 使能 EPIT1 中断并注册中断处理函数*/
GIC_EnableIRQ(EPIT1_IRQn);
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 : 无3.0
* @return : 无
*/
void gpio1_16_31_irqhandler(void)
{
filtertimer_restart(66000000/100); /* 开启定时器 */
gpio_clearIntFlags(GPIO1, 18); /* 清除中断标志位 */
}
main.c
#include "imx6ul.h"
#include "bsp_led.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_exit.h"
#include "bsp_epittimer.h"
#include "bsp_keyfilter.h"
/*
* @description : mian函数
* @param : 无
* @return : 无
*/
int main(void)
{
uint8_t state = OFF;
/* 对于中断的初始化,一定要放在代码的最前面 */
int_init();
clk_init(); /* 系统时钟初始化 */
clk_enable(); /* 使能所有的时钟 */
led_init(); /* 初始化led */
beep_init(); /* 初始化beep */
filterkey_init(); /* 带有消抖功能的按键 */
while(1) /* 死循环 */
{
state = !state;
led_switch(LED0, state);
delay(500);
}
return 0;
}
主要是给自己看的,所以肯定会出现很多错误哈哈哈哈哈
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律