- 定时器消抖工作原理
- 在按键按下之后,进入中断处理函数,在中断处理函数中,定时时间10ms
- 当定时时间到,执行定时器处理函数,在定时器处理函数中,读取管脚的电平状态
- 如果读到的是低电平,表示按键按下
- 编写设备树
-
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/timer.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
/*
myled{extend-led{led1 = <&gpioe 10 0>; //LED1 PE10led2 = <&gpiof 10 0>; //LED2 PF10led3 = <&gpioe 8 0>; //LED3 PE8};core-led{"led" = <&gpioz 5 0>,<&gpioz 6 0>,<&gpioz 7 0>; //LED1 PE10};
};mykey{interrupt-parent = <&gpiof>;interrupts = <9 0>,<7 0>,<8 0>;
};
*/
struct device_node *node;
int gpiono;
char *name[3] = {"led1", "led2", "led3"};struct timer_list mytimer; // 分配定时器对象
// 定时器处理函数
void timer_func(struct timer_list *timer)
{int i = gpio_get_value(gpiono); if(i==0){printk("引脚为低电平");}else{printk("引脚为高电平");}
}int irqno;
// 中断处理函数
irqreturn_t key_irq_handler(int irq, void *dev)
{printk("key1 down!!!!!\n");mytimer.expires = jiffies + 100; // 定时时间为1stimer_setup(&mytimer, timer_func, 0); // 定时器初始化add_timer(&mytimer); // 启动定时器return IRQ_HANDLED; // 表示中断处理完成
}// 入口
static int __init demo_init(void)
{int ret;// 解析设备树节点信息node = of_find_node_by_name(NULL, "myled"); // 通过节点的名字获取节点相关信息if (node == NULL){printk("of find node by name is error\n");return -EIO;}// 映射软中断号irqno = irq_of_parse_and_map(node, 0);if (irqno < 0){printk("irq of parse and map is error\n");return -EIO;}gpiono = of_get_named_gpio(node, name[0], 0);if (gpiono < 0){printk("of get named gpio is error");return -EIO;}// 注册中断子系统ret = request_irq(irqno, key_irq_handler, IRQF_TRIGGER_FALLING, "KEY1", NULL);if (ret){printk("request irq is error\n");return -EIO;}return 0;
}// 出口 卸载驱动 LED1熄灭
static void __exit demo_exit(void)
{//设置gpio编号输出低电平gpio_direction_output(gpiono, 0);// 释放gpio编号gpio_free(gpiono);del_timer(&mytimer);// 注销中断free_irq(irqno, NULL);
}module_init(demo_init); // 指定入口地址
module_exit(demo_exit); // 指定出口地址
MODULE_LICENSE("GPL"); // 遵循GPL协议