Linux按键驱动程序、定时器消抖

使用定时器可以防止因为按键抖动产生的多次响应函数~~


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/timer.h>
#include <linux/percpu.h>

#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>

#define BUT_NAME "buttons"
#define DEVCOUNT 1


struct dev_button
{
	dev_t dev;
	struct cdev *cdev_p;
	struct class * clz;
	struct class_device * clz_dev;
	struct timer_list timer;
};

struct key_dev
{
	char * name;	
	const int irq_num;
	unsigned int pin;
	unsigned int key_status;
};


struct dev_button button_device;
struct key_dev keys[] = {
	{.name = "S2", .irq_num = IRQ_EINT0, .pin = S3C2410_GPF0, .key_status = 0},
	{.name = "s3", .irq_num = IRQ_EINT2, .pin = S3C2410_GPF2, .key_status = 0},
	{.name = "s4", .irq_num = IRQ_EINT11, .pin = S3C2410_GPG3, .key_status = 0},
};


void timer_function(unsigned long data)
{
	struct key_dev * p_dev = (struct key_dev *)data;
	if(p_dev)
	{
		if(p_dev->key_status)
			printk("Key %s pressed!\n", p_dev->name);
		else
			printk("Key %s unpressed!\n", p_dev->name);
	}
	
	
}

irqreturn_t key_handler(int irq, void * param)
{		
	struct key_dev * p_dev = (struct key_dev *)param;
	if(p_dev)
	{
		button_device.timer.data = (unsigned long)p_dev;					
		if(s3c2410_gpio_getpin(p_dev->pin))		
			p_dev->key_status = 0;		
		else		
			p_dev->key_status = 1;		
		mod_timer(&(button_device.timer), jiffies + HZ/100);
	}
	
	return 0;
}


struct file_operations f_ops = {
	.owner = THIS_MODULE,
};

static int __init buttons_init(void)
{
	int error = 0;
	ssize_t i = 0;
	printk("Button's driver is installing...\n");
	if ((error = alloc_chrdev_region(&(button_device.dev), 0, DEVCOUNT, BUT_NAME)) < 0) {
		printk(KERN_ERR
		       "button: Couldn't alloc_chrdev_region, error=%d\n",
		       error);
		goto ERR_REG_DEVT;
	}
	printk("Alloc character region(%d, %d).\n",
		MAJOR(button_device.dev), MINOR(button_device.dev));
	
	button_device.cdev_p = cdev_alloc();
	if(NULL == button_device.cdev_p)	
	{
		printk(KERN_ERR
		       "button: Couldn't cdev_alloc");
		goto ERR_ALLOC;
	}
	printk("Alloc cdev struct.\n");
	
	button_device.cdev_p->ops = &f_ops;

	error = cdev_add(button_device.cdev_p, button_device.dev, DEVCOUNT);
	if(error < 0)
	{
		printk(KERN_ERR
		       "button: Couldn't cdev_add");
		goto ERR_ADD_DEV;
	}
	printk("Add character device.\n");
	
	button_device.clz = class_create(THIS_MODULE, BUT_NAME);
	if(button_device.clz == NULL)
	{
		printk(KERN_ERR
		       "button: Couldn't class_create");
		goto ERR_CLASS_CREATE;
	}
	printk("create class...\n");

	button_device.clz_dev = class_device_create(button_device.clz, NULL, button_device.dev, NULL, BUT_NAME);
	if(NULL == button_device.clz_dev)
	{
		printk(KERN_ERR
		       "button: Couldn't class_device_create");
		goto ERR_DEV_CREATE;
	}
	printk("create device...\n");

	printk("Button's driver installed successfully.\n");


	for(i = 0; i < sizeof(keys)/sizeof(struct key_dev); i++)
	{
		if(0 != request_irq(keys[i].irq_num, key_handler, IRQT_BOTHEDGE, keys[i].name, (void*)(keys + i)))
		{
			printk(KERN_ERR
		       "button: Couldn't request_irq %s\n", keys[i].name);
			goto ERR_REQUEST_IRQ;
		}
		printk("request_irq %d %s successfully\n", keys[i].irq_num,
			keys[i].name);
	}

	init_timer(&button_device.timer);
	button_device.timer.function = &timer_function;
	add_timer(&button_device.timer);			
	return 0;	
ERR_REQUEST_IRQ:
	for( i-=1 ; i >= 0; i--)
		free_irq(keys[i].irq_num, NULL);			
ERR_DEV_CREATE:
	class_destroy(button_device.clz);
ERR_CLASS_CREATE:
	cdev_del(button_device.cdev_p);
ERR_ADD_DEV:
	kfree(button_device.cdev_p);
ERR_ALLOC:
	unregister_chrdev_region(button_device.dev, DEVCOUNT);
ERR_REG_DEVT:	

	printk("Error happened!\n");
	return -1;
}


static void __exit buttons_exit(void)
{
	ssize_t i = 0;
	device_destroy(button_device.clz, button_device.dev);	
	class_destroy(button_device.clz);
	kfree(button_device.cdev_p);
	unregister_chrdev_region(button_device.dev, DEVCOUNT);

	del_timer(&(button_device.timer));
	
	for( i = 0 ; i < sizeof(keys) / sizeof(struct key_dev); i++)
		free_irq(keys[i].irq_num, (void*)(keys + i));	
	return ;
}

module_init(buttons_init);
module_exit(buttons_exit);

MODULE_LICENSE("GPL");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值