nuc977 linux 按键中断+定时器消抖

32 篇文章 8 订阅

10ms消抖时间测试效果不错!

drv_buttons2.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 "buttons2" /* 名字 */


/*  设备结构体 */
struct buttons2_dev{
	dev_t devid; /* 设备号 */
	struct cdev cdev; /* cdev */
	struct class *class; /* 类 */
	struct device *device; /* 设备 */
	int major; /* 主设备号 */
	int minor; /* 次设备号 */
	struct timer_list timer; /* 定义一个定时器*/
	int keyvalue;/*有效按键值*/
	
};
struct buttons2_dev buttons; /* led 设备 */


struct pin_desc{
	int pin;
	int val;
	unsigned long flags;
	char *name;
	int releasekey; /* 标记是否完成一次完成的按键  1 表示完成*/
	int key_down;   /* 1 表示检测到中断*/
	};


static struct pin_desc pins_desc[3] = {
	{NUC970_PB2, 0x1,IRQF_TRIGGER_FALLING,"KEY1",0,0},
	{NUC970_PB3, 0x2,IRQF_TRIGGER_FALLING,"KEY2",0,0},
	{NUC970_PB4, 0x3,IRQF_TRIGGER_FALLING,"KEY3",0,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)
{
    struct buttons2_dev *dev = (struct buttons2_dev *)filp->private_data;
	

	if (dev->keyvalue>0x80)
    {
    	/* 将按键状态复制给用户,并清0 */   
		copy_to_user(buf, &dev->keyvalue, 1);			
		dev->keyvalue=0;
		return 0;
    }
	else
	{
		return -EINVAL;
	}
	
}



/* 设备操作函数 */
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;	

	buttons.keyvalue= pin->val; 
	pin->key_down=1;	

	mod_timer(&buttons.timer,jiffies+msecs_to_jiffies(10));//10MS后
	
	return IRQ_RETVAL(IRQ_HANDLED);


}


/*定时器回调函数 */
void timer_function(unsigned long arg)
{
	struct buttons2_dev *dev = (struct buttons2_dev *)arg;
	int i;
	int value;
	struct pin_desc *p_pin=pins_desc;
	if (dev->keyvalue==0)
		return;

	for(i=0;i<3;i++)
	{
		if (p_pin->key_down)
		{
			value=gpio_get_value(p_pin->pin);
			if (value==0)//还在有按下
			{
				dev->keyvalue=0x80|p_pin->val;				
			}
			else//没有按下,本次取消
			{
				dev->keyvalue=0;
			}
			p_pin->key_down=0;//清0
			
		}
		p_pin++;
	}
	

}





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);
	}	

	/*6. 初始化timer,设置定时器处理函数,还未设置周期,所以不会激活定时器*/
	init_timer(&buttons.timer);
	buttons.timer.function=timer_function;
	buttons.timer.data=(unsigned long)&buttons;


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

	return 0;
}

static void __exit nuc977_buttons_exit(void)
{

	int i;

	del_timer_sync(&buttons.timer);/*  删除定时器*/
	
	/* 注销字符设备 */
	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_button2.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;
	int ret=0;

	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)
	{
				
		ret=read(fd, &key_val, 1);
		if (ret==0)//返回正确
		{
			printf("key_val = 0x%x\n", key_val);
		}
		else
		{

		}
		
	}

	close(fd);

	return 0;
}




 

secureCTR

BusyBox v1.22.1 (2016-02-03 14:11:04 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

~ # ifconfig eth0 192.168.0.4 up
nuc970-emac0 nuc970-emac0: eth0 is OPENED
~ # mount -o nolock -t nfs 192.168.0.199:/home/hbin/nfs /mnt
~ # cd /mnt/
/mnt # cd driver/
/mnt/driver # ls
drv_buttons     drv_hello       drv_led2        drv_timer
drv_buttons2    drv_led         drv_newcharled
/mnt/driver # cd drv_buttons2
/mnt/driver/drv_buttons2 # ls
Makefile            built-in.o          drv_buttons2.mod.c  modules.order
Makefile.bak        drv_buttons2.c      drv_buttons2.mod.o
Module.symvers      drv_buttons2.ko     drv_buttons2.o
/mnt/driver/drv_buttons2 # lsmod
/mnt/driver/drv_buttons2 # ls /lib/modules/
3.10.101           drv_buttons2.ko    drv_led.ko         drv_newcharled.ko
drv_buttons.ko     drv_hello.ko       drv_led2.ko        drv_timer.ko
/mnt/driver/drv_buttons2 # rm drv_buttons2.ko
/mnt/driver/drv_buttons2 # ls /lib/modules/
3.10.101           drv_buttons2.ko    drv_led.ko         drv_newcharled.ko
drv_buttons.ko     drv_hello.ko       drv_led2.ko        drv_timer.ko
/mnt/driver/drv_buttons2 # rm /lib/modules/drv_buttons2.ko
/mnt/driver/drv_buttons2 # ls /lib/modules/
3.10.101           drv_hello.ko       drv_led2.ko        drv_timer.ko
drv_buttons.ko     drv_led.ko         drv_newcharled.ko
/mnt/driver/drv_buttons2 # ls
Makefile            built-in.o          drv_buttons2.mod.c  modules.order
Makefile.bak        drv_buttons2.c      drv_buttons2.mod.o
Module.symvers      drv_buttons2.ko     drv_buttons2.o
/mnt/driver/drv_buttons2 # cp drv_buttons2.ko /lib/modules/
/mnt/driver/drv_buttons2 # insmod /lib/modules/drv_buttons2.ko
buttons major=252,minor=0
buttons module initialized
/mnt/driver/drv_buttons2 # lsmod
drv_buttons2 1613 0 - Live 0xbf000000 (O)
/mnt/driver/drv_buttons2 # cd ../..
/mnt # ls
app        driver     rootfs_hb
/mnt # cd app/
/mnt/app # ls
app_button        app_led           app_newcharled    app_timer2
app_button.c      app_led.c         app_newcharled.c  app_timer2.c
app_button2       app_led2          app_timer         helloworld
app_button2.c     app_led2.c        app_timer.c       helloworld.c
/mnt/app # ./app_button2 /dev/buttons2 
 argv[0]= ./app_button2 
 argv[1]= /dev/buttons2 
key_val = 0x81
key_val = 0x83
key_val = 0x81
key_val = 0x81
key_val = 0x81
key_val = 0x81
key_val = 0x81
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x83
key_val = 0x81
key_val = 0x81
key_val = 0x81
key_val = 0x81

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值