linux 驱动 -》按键 中断 request_irq 延时防抖mod_timer

/* 按键的消抖*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/uaccess.h>

int major=250;
int minor=0;
dev_t devno;
struct cdev cdev;
static struct class *cls;
static struct device *test_device;
static struct resource *key_res1;
static struct resource *key_res2;
static  int key_num;
wait_queue_head_t rq; //定义队列的头
static int flage=0;


//定时器的结构体
static struct timer_list key_timer;

static  int hello_open (struct inode *inode, struct file *filep)
{
       printk("hello_open enter completed...\n");
       return 0;
}
static  int hello_release(struct inode *inode, struct file *filep)
{
       printk("hello_release completed...\n");
       return 0;
}
static ssize_t hello_read (struct file *filep, char __user *buf, size_t len, loff_t *pos)
{
	if(len !=4)
	{
		return -EINVAL;
	}
	printk("  block of...get data and read data send to user\n");
	
	wait_event_interruptible(rq, flage!=0);
	
	if(copy_to_user(buf,&key_num,sizeof(int)))
	{
		return -EFAULT;
	}
	printk("send  date  to user sucessfully...\n");
	flage = 0;
	return len;
}
struct file_operations hello_ops =
{
      .open = hello_open,
	  .read = hello_read,
	  .release = hello_release,
};
/*如果按键抖动 会执行n 次 该回调函数 最后按键稳定了 才会执行key_timer_handler*/
 static irqreturn_t key_handler(int irqnum, void *dev_id)
 {
	//printk("irqnum = %d \n",irqnum);

     key_timer.expires = jiffies + 500;
	/*???ˉ?óê±£?*/
	
	key_timer.data = irqnum;
	
	mod_timer(&key_timer, key_timer.expires); //修改该定时器
	
	printk("some time after ---> enter timer...\n");
	
	return IRQ_HANDLED;
 }
 /*中断函数可能调用很多次 但定时器函数只调用一次 key_handler执行时间到了才会执行key_timer_handler 否者不会 这就是原理*/
static void key_timer_handler(unsigned long irqnum)
{
	printk("enter timer.....\n");
	if( key_res1->start == key_timer.data)
	{
			key_num =1;
	}

	if( key_res2->start == key_timer.data)
	{		key_num =2;

	}
	 flage = 1 ;
	 printk("wake up block....\n");
	 wake_up_interruptible(&rq);
}
static 	int key_probe(struct platform_device *pdev)
{
	int ret;

	key_res1 = platform_get_resource(pdev,IORESOURCE_IRQ, 0);
	key_res2 = platform_get_resource(pdev,IORESOURCE_IRQ, 1);

	ret = request_irq(key_res1->start, key_handler, key_res1->flags, "key1", NULL);
	
	ret = request_irq(key_res2->start, key_handler, key_res2->flags, "key2", NULL);

	ret = register_chrdev(major,"hello",&hello_ops);
	printk("major = %d \n", ret);
	
	//产生设备节点
	devno = MKDEV(major,minor);
	cls = class_create(THIS_MODULE,"hello1");
	if(IS_ERR(cls))
	{
	    unregister_chrdev(major,"hello");
		return -EBUSY;
	}
	test_device = device_create(cls,NULL,devno,NULL,"dev_node");
	
	if(IS_ERR(test_device))
	{
		class_destroy(cls);
		unregister_chrdev(major,"hello");
		return -EBUSY;
	}
	
	init_waitqueue_head(&rq);
	
	
	//初始化定时器
	init_timer(&key_timer);
	
	key_timer.function = key_timer_handler;  //注意:此条语句属于初始化,
	
	//添加(注册)定时器
	add_timer(&key_timer);
	

	return 0;
}
static 	int key_remove(struct platform_device *pdev)
{
	del_timer(&key_timer);
	free_irq(key_res1->start, NULL);
	free_irq(key_res2->start, NULL);
	
	device_destroy(cls,devno);
	class_destroy(cls);
	unregister_chrdev(major,"hello");
	
	return 0;
}
static  struct of_device_id	key_id[]=
{
		{.compatible = "fs4412,key"},
};
static struct platform_driver key_driver=
{
	.probe = key_probe,
	.remove = key_remove,
	.driver =
	{
		.name="fs4412-key",
		.of_match_table = key_id,
	},
};
static int pwmdev_init(void)
{
	return platform_driver_register(&key_driver);

}
static void pwmdev_exit(void)
{
	 platform_driver_unregister(&key_driver);
	return;
}
//module_param(devno,uint,0600);
MODULE_LICENSE("GPL");
module_init(pwmdev_init);
module_exit(pwmdev_exit);
//insmod hello.ko major=249

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值