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