按键中断,定时器消抖点亮LED 2011-08-25 10:42:14| 分类: linux驱动源码 | 标签: |字号大中小 订阅 .
/**********************头文件等的使用*******************************/
#include <linux/module.h> //一定要
#include <linux/kernel.h> //printk
#include <linux/irq.h> //中断IRQ_EINT等的定义
#include <linux/interrupt.h> //request_irq,free_irq等的使用
#include <linux/fs.h> //file_operations
#include <linux/init.h> //__init等的使用
#include <linux/cdev.h> //cdev注册
#include <linux/errno.h> //错误信息
#include <linux/types.h> //size_t和ssize_t等的使用
#include <linux/device.h> //class_create创造
#include <mach/regs-gpio.h> //所以的gpio端口的定义都在这里
#include <mach/hardware.h> //setpin等的使用
#include <asm/uaccess.h> //copy_to_user等的使用
/
/********************全局变量,常量等的使用**************************/
#define BUTTON_MAJOR 19 //主设备号
#define BUTTON_NAME "zheng_he_xiang" //设备名字
#define BUTTON_NUM 4 //键盘数量
#define BUTTON_ON 1 //键盘被按下
#define BUTTON_OFF 0 //键盘没被按下
#define BUTTON_DELAY (HZ/50) //延时时间
#define LED_ON 0 //灯亮
#define LED_OFF 1 //灯灭
//
static int button_major=BUTTON_MAJOR; //主设备号
//
/************************结构体的定义******************************/
struct button_dev
{
struct cdev cdev; //cdev
};
//
static struct button_dev *button_devp; //定义pointer
//
struct button_irq_desc
{
unsigned int irq; //中断号
unsigned int button_pin; //按键端口
unsigned int button_pin_setting;//按键端口设置
unsigned int number; //按键值
char *name; //该按键中断的名字
unsigned int led_pin; //led所在的端口
unsigned int led_pin_setting; //led所在端口的设置
unsigned int key_status;
};
/
static struct button_irq_desc button_number[]=
{
{IRQ_EINT0,S3C2410_GPF0,S3C2410_GPF0_EINT0,0,"Key0",S3C2410_GPB5,S3C2410_GPB5_OUTP,0},
{IRQ_EINT1,S3C2410_GPF1,S3C2410_GPF1_EINT1,1,"Key1",S3C2410_GPB6,S3C2410_GPB6_OUTP,0},
{IRQ_EINT2,S3C2410_GPF2,S3C2410_GPF2_EINT2,2,"Key2",S3C2410_GPB7,S3C2410_GPB7_OUTP,0},
{IRQ_EINT4,S3C2410_GPF4,S3C2410_GPF4_EINT4,3,"KEy4",S3C2410_GPB8,S3C2410_GPB8_OUTP,0},
}; //数组定义
/
static struct timer_list button_timer[BUTTON_NUM];//定时器设置
自动加载节点
struct class *button_class;//自动加载节点
/****************************************定时器中断处理函数***********************************/
static void button_timer_handle(unsigned long data)
{
int ret=0;
unsigned int num=(unsigned int)data;
printk("num is %d\n",num);
ret=s3c2410_gpio_getpin(button_number[num].button_pin);
printk("ret is %d\n",ret);
if(ret==0)
{
s3c2410_gpio_setpin(button_number[num].led_pin,LED_ON);
}
if(ret>0)
{
s3c2410_gpio_setpin(button_number[num].led_pin,LED_OFF);
}
}
/**************************************按键中断处理函数**************************************/
static irqreturn_t button_interrupt(int irq,void *dev_id)
{
struct button_irq_desc *button=(struct button_irq_desc *)dev_id;//把参数给button
int ret;
ret=s3c2410_gpio_getpin(button->button_pin);
del_timer(&button_timer[button->number]);
setup_timer(&button_timer[button->number],button_timer_handle,button->number);
button_timer[button->number].expires=jiffies+BUTTON_DELAY;
add_timer(&button_timer[button->number]);
if(ret)
{
//s3c2410_gpio_setpin(button->led_pin,LED_OFF);
button->key_status=0;
printk("LED_ON key_status is %d\n",button->key_status);
}
else
{
//s3c2410_gpio_setpin(button->led_pin,LED_ON);
button->key_status=1;
printk("LED_OFF key_status is %d\n",button->key_status);
}
printk("EN the button..num is %d\n",button->number);
return IRQ_HANDLED;
}
///
/*******************************************打开函数*****************************************/
static int button_open(struct inode *inode,struct file *file)
{
//file->private_data=button_devp;//给私有参数
int i;
int ret;//返回值
local_irq_disable();
printk("local_irq_disable\n");
for(i=0;i<sizeof(button_number)/sizeof(button_number[0]);i++)
{
/***************定时器初始化****************/
setup_timer(&button_timer[i],button_timer_handle,i);
button_timer[i].expires=jiffies+BUTTON_DELAY;
//add_timer(&button_timer[i]);
/*****************端口初始化****************/
s3c2410_gpio_cfgpin(button_number[i].button_pin,button_number[i].button_pin_setting);
s3c2410_gpio_cfgpin(button_number[i].led_pin,button_number[i].led_pin_setting);
s3c2410_gpio_setpin(button_number[i].led_pin,LED_OFF);//关灯
/*****************初始化中断*****************/
ret=request_irq(button_number[i].irq,button_interrupt,IRQ_TYPE_EDGE_BOTH,button_number[i].name,&button_number[i]);
if(ret)
{
break;
}
}
if(ret)
{
i--;
for(;i>0;i--)
{
free_irq(button_number[i].irq,&button_number[i]);
printk("free irq err\n");
}
return ret;
}
local_irq_enable();
return 0;
}
//
/*********************************************关闭函数*********************************************/
static int button_close(struct inode *inode,struct file *file)
{
int i;
for(i=0;i<sizeof(button_number)/sizeof(button_number[0]);i++)
{
del_timer(&button_timer[i]);//删除中断
free_irq(button_number[i].irq,&button_number[i]);
}
return 0;
}
/*********************************************结构体********************************************/
static const struct file_operations button_fops=
{
.owner=THIS_MODULE,
.open=button_open,
.release=button_close,
};
/
/****************************cdev注册函数***************************************/
static void button_setup_cdev(struct button_dev *dev,int index)
{
int err;
dev_t devno=MKDEV(button_major,index);
cdev_init(&dev->cdev,&button_fops);
dev->cdev.owner=THIS_MODULE;
dev->cdev.ops=&button_fops;
err=cdev_add(&dev->cdev,devno,1);
if(err)
{
printk(KERN_NOTICE "cdev err");
}
}
/**************************************模块加载函数***********************************/
static __init int button_init(void)
{
int result;
dev_t devno=MKDEV(button_major,0);
if(button_major)
{
result=register_chrdev_region(devno,1,BUTTON_NAME);
}
else
{
result=alloc_chrdev_region(&devno,0,1,BUTTON_NAME);
button_major=MAJOR(devno);
}
if(result<0)
{
return result;
}
printk("region ok ...\n");
button_devp=kmalloc(sizeof(struct button_dev),GFP_KERNEL);
if(!button_devp)
{
result=-ENOMEM;
goto fail_malloc;
}
printk("kmalloc ok ...\n");
memset(button_devp,0,sizeof(struct button_dev));//清0
button_setup_cdev(button_devp,0);
/
button_class = class_create(THIS_MODULE, BUTTON_NAME);
if(IS_ERR(button_class))
{
printk("Err: failed in creating class.\n");
return -1;
}
/* register your own device in sysfs, and this will cause udev to create corresponding device node */
device_create( button_class, NULL, MKDEV(button_major, 0), NULL, BUTTON_NAME );
printk("device ok ...\n");
//
return 0;
fail_malloc:unregister_chrdev_region(devno,1);
return result;
}
/
/************************************卸载函数**********************************/
static void __exit button_exit(void)
{
cdev_del(&button_devp->cdev);
kfree(button_devp);
unregister_chrdev