nuc977 linux 按键中断 未消抖

32 篇文章 8 订阅

drv_buttons.c

 

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/delay.h>

#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-gcr.h>

#include <mach/irqs.h>
#include <linux/fs.h>
#include <linux/cdev.h>

#include <linux/uaccess.h> // copy_from_user


#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/pinctrl/consumer.h>
#include <linux/err.h>
#include <linux/kdev_t.h>
#include <asm/io.h>
#include <linux/sched.h>


#define BUTTONS_CNT 1 /* 设备号个数 */
#define BUTTONS_NAME "buttons" /* 名字 */


/*  设备结构体 */
struct buttons_dev{
	dev_t devid; /* 设备号 */
	struct cdev cdev; /* cdev */
	struct class *class; /* 类 */

	struct device *device; /* 设备 */
	int major; /* 主设备号 */
	int minor; /* 次设备号 */
};
struct buttons_dev buttons; /* led 设备 */


struct pin_desc{
	int pin;
	int val;
	unsigned long flags;
	char *name;
};


static struct pin_desc pins_desc[3] = {
	{NUC970_PB2, 0x1,IRQF_TRIGGER_FALLING,"KEY1"},
	{NUC970_PB3, 0x2,IRQF_TRIGGER_FALLING,"KEY2"},
	{NUC970_PB4, 0x3,IRQF_TRIGGER_FALLING,"KEY3"},
};


static unsigned char val;

static DECLARE_WAIT_QUEUE_HEAD(buttons_waitq);

/* 中断事件标志, 中断服务程序将它置1,nuc977_buttons_read 将它清0 */
static volatile int ev_press = 0;


static int nuc977_buttons_open(struct inode *ino, struct file *file)
{
	file->private_data = &buttons; /* 设置私有数据 */
	return 0;
}

static ssize_t nuc977_buttons_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{

	unsigned long err;
    
    /* 如果ev_press等于0,休眠 */
    wait_event_interruptible(buttons_waitq, ev_press);

    /* 执行到这里时,ev_press等于1,将它清0 */
    ev_press = 0;

    /* 将按键状态复制给用户,并清0 */   
	copy_to_user(buf, &val, 1);
	val=0;
   
	return 0;
}



/* 设备操作函数 */
static struct file_operations buttons_fops = {
	.owner = THIS_MODULE,
	.open = nuc977_buttons_open,	
	.read = nuc977_buttons_read,	
};


static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
	struct pin_desc *pin = (struct pin_desc *)dev_id;
	
	val = 0x80 | pin->val; 
	ev_press = 1;
	wake_up_interruptible(&buttons_waitq);

	return IRQ_RETVAL(IRQ_HANDLED);


}


static int keyio_init(void)
{

	int i;
    int err;
    
    for (i = 0; i < sizeof(pins_desc)/sizeof(pins_desc[0]); i++) {
        // 注册中断处理函数
        err = request_irq(gpio_to_irq(pins_desc[i].pin), buttons_interrupt, pins_desc[i].flags, 
                          pins_desc[i].name, (void *)&pins_desc[i]);
        if (err)
            break;
    }

    if (err) {
		printk("keyio_init err **********\r\n");
        // 释放已经注册的中断
        i--;
        for (; i >= 0; i--)
            free_irq(gpio_to_irq(pins_desc[i].pin), (void *)&pins_desc[i]);
        return -EBUSY;
    }
    
    return 0;

	
}




static int __init nuc977_buttons_init(void)
{

	/* 注册字符设备驱动 */
	/* 1、创建设备号 */
	if (buttons.major) { /* 定义了设备号 */
		buttons.devid = MKDEV(buttons.major, 0);
		register_chrdev_region(buttons.devid, BUTTONS_CNT,BUTTONS_NAME);
	}
	else 
	{ /* 没有定义设备号 */
		alloc_chrdev_region(&buttons.devid, 0, BUTTONS_CNT,	BUTTONS_NAME); /* 申请设备号 */
		buttons.major = MAJOR(buttons.devid); /* 获取主设备号 */
		buttons.minor = MINOR(buttons.devid); /* 获取次设备号 */
	}
	printk("buttons major=%d,minor=%d\r\n",buttons.major,buttons.minor);


	/* 2、初始化 cdev */
	buttons.cdev.owner = THIS_MODULE;
	cdev_init(&buttons.cdev, &buttons_fops);

	/* 3、添加一个 cdev */
	cdev_add(&buttons.cdev, buttons.devid, BUTTONS_CNT);

	/* 4、创建类 */
	buttons.class = class_create(THIS_MODULE, BUTTONS_NAME);
	if (IS_ERR(buttons.class)) {
		return PTR_ERR(buttons.class);
	}

	/* 5、创建设备 */
	buttons.device = device_create(buttons.class, NULL,
	buttons.devid, NULL, BUTTONS_NAME);
	if (IS_ERR(buttons.device)) {
		return PTR_ERR(buttons.device);
	}	

	keyio_init();
	
	printk(KERN_INFO "buttons module initialized\n");

	return 0;
}

static void __exit nuc977_buttons_exit(void)
{

	int i;
	/* 注销字符设备 */
	cdev_del(&buttons.cdev);/* 删除 cdev */
	unregister_chrdev_region(buttons.devid, BUTTONS_CNT);

	device_destroy(buttons.class, buttons.devid);
	class_destroy(buttons.class);
	   
    for (i = 0; i < sizeof(pins_desc)/sizeof(pins_desc[0]); i++) {
        // 释放已经注册的中断
        free_irq(gpio_to_irq(pins_desc[i].pin), (void *)&pins_desc[i]);
    }
	
	printk(KERN_INFO "nuc977_buttons_exit module exited\n");
	
}

module_init(nuc977_buttons_init);
module_exit(nuc977_buttons_exit);
MODULE_LICENSE("GPL");






 

app_button.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "string.h"

#include "linux/ioctl.h"


int main(int argc, char *argv[])
{   
	int fd,i;
	char *filename;
	unsigned char key_val;

		

	for(i=0;i<argc;i++)
		printf(" argv[%d]= %s \n",i,argv[i]);	
	
	
	filename=argv[1];
	fd = open(filename, O_RDWR);  // 打开设备
	if (fd < 0) {
	    printf("Can't open  %s \n",argv[1]);
	    return -1;
	}


	while(1)
	{
				
		read(fd, &key_val, 1);
		printf("key_val = 0x%x\n", key_val);

	}

	close(fd);

	return 0;
}




/mnt/driver/drv_buttons # insmod /lib/modules/drv_buttons.ko 
buttons major=252,minor=0
buttons module initialized
/mnt/driver/drv_buttons # lsmod
drv_buttons 1550 0 - Live 0xbf000000 (O)

 

/mnt/app # ./app_button /dev/buttons 
 argv[0]= ./app_button 
 argv[1]= /dev/buttons 
key_val = 0x81
key_val = 0x81
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x82
key_val = 0x82
key_val = 0x82
key_val = 0x82
key_val = 0x82
key_val = 0x82
key_val = 0x82
key_val = 0x82
key_val = 0x81
key_val = 0x81
key_val = 0x81
key_val = 0x81
key_val = 0x81
key_val = 0x81

 

因为没消抖,所以按一下会输出多次。

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值