您好,欢迎访问一九零五行业门户网

kernel2.6.32.2 mini2440 led 驱动 之 中断(去抖动)处理

#include linux/module.h #include linux/init.h #include linux/mm.h #include linux/slab.h #include linux/types.h #include linux/semaphore.h #include linux/cdev.h #include linux/fs.h #include linux/semaphore.h #include linux/irq.h #include asm
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define led_major 250
#define led_name leds
#define key_count 4
#define key_delay hz/50
declare_wait_queue_head(r_wait);  //初始化等待队列
//wait_queue_head_t r_wait;
//init_waitqueue_head(&r_wait);
static struct timer_list key_timers[key_count];  //定义定时器
static volatile bool idetify;
static void buttons_timer(unsigned long);
static unsigned long led_table [] = {
    s3c2410_gpb(5),
    s3c2410_gpb(6),
    s3c2410_gpb(7),
    s3c2410_gpb(8),
};//位地址
static unsigned int led_cfg_table [] = {
    s3c2410_gpio_output,
    s3c2410_gpio_output,
    s3c2410_gpio_output,
    s3c2410_gpio_output,
};//控制led为输入
struct button_irq_key{
    int irq;
    int pin;
    unsigned long flags;
    char *name;
};
static struct button_irq_key button_irqs[] = {
    {irq_eint8, s3c2410_gpg(0), irqf_trigger_falling, key1},
    {irq_eint11, s3c2410_gpg(3), irqf_trigger_falling, key2},
    {irq_eint13, s3c2410_gpg(5), irqf_trigger_falling, key3},
    {irq_eint14, s3c2410_gpg(6), irqf_trigger_falling, key4},
};
static volatile int press_cnt[] = {0, 0, 0, 0};
static volatile int pressed = 0;
struct leds_cdev
{
    struct cdev cdev;
    struct semaphore sem;
};
int leds_major = led_major;
struct leds_cdev dev;
static irqreturn_t buttons_interrupt(int irq, void *dev_id)//按键中断处理函数
{
//    volatile int *press_count = (volatile int*)dev_id;
//disable_irq(irq);
    int key = 0;
switch(irq){
    case 52:
    key = 0;
    break;
    case 55:
    key = 1;
    break;
    case 57:
    key = 2;
    break;
    case 58:
    key = 3;
    break;
    default:break;
}
key_timers[key].data = key;
    mod_timer(&key_timers[key], jiffies + key_delay);
    printk(kern_emerg irq success);
    return irq_handled;
}
static void buttons_timer(unsigned long arg)//定时器中断处理函数,去抖实现
{
    int key = arg;
    int condition;
    int nf;
    condition = s3c2410_gpio_getpin(button_irqs[key].pin);
    if(!condition)
    {
    while(!s3c2410_gpio_getpin(button_irqs[key].pin));
key_timers[key].expires = jiffies + key_delay;
    add_timer(&key_timers[key]);
    idetify = 1;
printk(kern_emerg lower is appear);
    }else{
if(!idetify)
    return;
press_cnt[key] += 1;
    nf = press_cnt[key]%2;
    s3c2410_gpio_setpin(led_table[key], nf);
pressed = 1;
    wake_up_interruptible(&r_wait);
    idetify = 0;
printk(kern_emerg up is appear%d, nf);
//    enable_irq(button_irqs[key].irq);
    }
//    printk(kern_emerg success of interruptible);
}
static int led_buttons_open(struct inode *inode, struct file *filp)
{
    int i;
    int err;
    for(i = 0; i     err = request_irq(button_irqs[i].irq, buttons_interrupt,
                button_irqs[i].flags, button_irqs[i].name, (void*)&press_cnt[i]); //请求中断
    if(err)
    break;
/*    init_timer(&key_timers[i]);
    key_timers[i].data = i;
    key_timers[i].function = buttons_timer;
*/
    setup_timer(&key_timers[i], buttons_timer, i);初始化定时器
    }
    //key_timers[0].expires = jiffies + 3 * hz;
    //add_timer(&key_timers[0]);
    if(err){
    i--;
    for(; i >= 0; i--)
    free_irq(button_irqs[i].irq, (void *)press_cnt[i]);
    return -ebusy;
    }
return 0;
}
static ssize_t led_buttons_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
    unsigned long err;
    wait_event_interruptible(r_wait, pressed);
pressed = 0;
err = copy_to_user(buf, (const void *)press_cnt, sizeof(press_cnt));
    memset((void *)press_cnt, 0, sizeof(press_cnt));
    return err ? -efault : 0 ;
}
static int led_buttons_close(struct inode *inode, struct file *filp)
{
    int i;
    for(i = 0; i     free_irq(button_irqs[i].irq, (void*)&press_cnt[i]);//释放中断号
    del_timer(&key_timers[i]);
    }
    return 0;
}
static int leds_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    switch(cmd)
    {
        case 0:
        if(arg > 4){
            return -einval;
            }
        down(&dev.sem);
        s3c2410_gpio_setpin(led_table[arg], 0);
        up(&dev.sem);
        return 0;
        case 1:
        if(arg > 4){
        return -einval;
        }
        down(&dev.sem);
        s3c2410_gpio_setpin(led_table[arg], 1);
        up(&dev.sem);
        return 0;
        default:
            return -einval;
    }
}
struct file_operations cdev_fops = {
    .owner = this_module,
    .ioctl = leds_ioctl,
    .open = led_buttons_open,
    .read = led_buttons_read,
    .release = led_buttons_close,
};
static void leds_setup(struct leds_cdev *dev, int index)
{
    int err, devno = mkdev(leds_major, index);
    cdev_init(&dev->cdev, &cdev_fops);
    dev->cdev.owner = this_module;
    dev->cdev.ops = &cdev_fops;
    err = cdev_add(&dev->cdev, devno, 1);
    if(err)
        printk(kern_notice error %d adding led %d\n, err, index);
}
static int __init dev_init(void)       //module初始化与注册
{
    int result;
    int i;
//    struct class *my_class;
    dev_t devno = mkdev(leds_major, 0);
    for(i = 0; i     s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
    s3c2410_gpio_setpin(led_table[i], 0);
    }
if(leds_major)
    result = register_chrdev_region(devno, 1, leds);
    else{
    result = alloc_chrdev_region(&devno, 0, 1, leds);
    leds_major = devno;
    }
if(result     return result;
    leds_setup(&dev, 0);
    sema_init(&dev.sem, 1);
/*    my_class = class_create(this_module, led_name);
    if(is_err(my_class))
    {
    printk(err:failed in creating class.\n);
    return -1;
    }
    device_create(my_class, null, mkdev(leds_major, 0), led_name, 0);
*/
    return 0;
}
void __exit dev_exit(void)
{
    cdev_del(&dev.cdev);
    unregister_chrdev_region(mkdev(leds_major, 0), 1);
}
module_init(dev_init);
module_exit(dev_exit);
module_license(gpl);
module_author(emperor);
module_description(led module);
自行分析
亲测通过
如果bug,望大伙提出来,互相改善学习一下。
其它类似信息

推荐信息