查看: 1055|回复: 0
打印 上一主题 下一主题

arm驱动程序——按键程序3_定时器消抖(韦东山的视频总结及针对linux-2.6.30)

[复制链接]
跳转到指定楼层
沙发
发表于 2013-6-13 15:21:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
按键利用定时器消抖:

1.定义timer_list结构体的变量。

2.初始化定时器,

3.增加定时器,启动定时器。

所用到的结构体和函数等:

/*初始化时一般设置,expires,function,data*/

struct timer_list {

    /*定时器列表*/
    struct list_head entry;

    /*定时器的到期时间,是jiffies和HZ一起设置*/
    unsigned long expires;
    /*定时器的处理函数*/

    void (*function)(unsigned long);
    /*定时器的函数函数的参数*/  

    unsigned long data;

    struct tvec_base *base;

    #ifdef CONFIG_TIMER_STATS
    void *start_site;
    char start_comm[16];
    int start_pid;
    #endif
    #ifdef CONFIG_LOCKDEP
    struct lockdep_map lockdep_map;
    #endif
};

/*初始化函数,timer是timer_list结构体指针*/

#define init_timer(timer)\
init_timer_key((timer), NULL, NULL)

/*用setup_timer函数也可以初始定时器

* timer:timer_list的结构体指针,fn:定时器处理函数,

*data:定时器处理函数的参数

*/

#define setup_timer(timer, fn, data)\
setup_timer_key((timer), NULL, NULL, (fn), (data))



/*增加一个定时器,启动定时器,就是把定时器加入到内核定时器链表中*/

void add_timer(struct timer_list *timer)

/*修改定时器的超出时间的,timer;timer_list结构体指针,expires;定时器的超时时间*/

int mod_timer(struct timer_list *timer, unsigned long expires)


关于其它的函数及结构体和中断(linux中断体系架构与注册讲了)已经在前面讲述,不再多讲

驱动程序:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/irqs.h>
#include <mach/regs-gpio.h>
/*不同的linux内核,头文件会有所不同*/


/*用来保存主设备号*/
static unsigned long major;
/*定义类*/
static struct class *second_key_class;
/*定义类下的设备*/
static struct device *second_key_device;
/*中断时间标志,置1,用于唤醒休眠,睡眠时,将其置0*/
static volatile int en_press = 0;
/*用于保存按键值*/
static int key_val;
/*定义一个等待队列头文件*/
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
/*定义一个定时器*/
static struct timer_list key_timer;
void key_timer_function(unsigned long data);
struct pindec{
   unsigned long pin;
   unsigned long val;
};


struct pindec * irq_dec;
/*松开按键的值为0x01,0x02,0x3,0x04*/
/*按下按键时值为0x81,0x82,0x83,0x84*/
struct pindec pin_dec[4] = {
   {S3C2410_GPF0,0x04},
   {S3C2410_GPF1,0x01},
   {S3C2410_GPF2,0x03},
   {S3C2410_GPF4,0x02},
};
#if 0
struct pin_desc pins_desc[4] = {
   {S3C2410_GPF1,0x01},
   {S3C2410_GPF4,0x02},
   {S3C2410_GPF2,0x03},
   {S3C2410_GPF0,0x04},
};
#endif
/*中断处理函数*/
static irqreturn_t buttons_irq(int irq,void *dev_id)
{

   irq_dec = (struct pindec *)dev_id;
   mod_timer(&key_timer,jiffies+HZ/100);
   return IRQ_RETVAL(IRQ_HANDLED);
}
/*根据file_operations的open函数写*/
static int second_key_open(struct inode *inode, struct file *file)
{
   request_irq(IRQ_EINT1,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s1",&pin_dec[1]);
   request_irq(IRQ_EINT4,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s2",&pin_dec[3]);
   request_irq(IRQ_EINT2,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s3",&pin_dec[2]);
   request_irq(IRQ_EINT0,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s4",&pin_dec[0]);
   return 0;
}


/*根据file_operations的close函数写*/
static int second_key_close(struct inode *inode, struct file *file)
{
   free_irq(IRQ_EINT1,&pin_dec[1]);
   free_irq(IRQ_EINT4,&pin_dec[3]);
   free_irq(IRQ_EINT2,&pin_dec[2]);
   free_irq(IRQ_EINT0,&pin_dec[0]);
   return 0;
}


/*根据file_operations的read函数写*/
static ssize_t second_key_read(struct file *file, char __user *user_buffer,
                              size_t count, loff_t *ppos)
{
   if(count != 1)

      return -EINVAL;
    /*松开按键时*/
   wait_event_interruptible(button_waitq,en_press);
    /*按下按键时*/
   copy_to_user(user_buffer,&key_val,1);
    /*置0,睡眠*/
   en_press = 0;
   return 1;
}
/*定义一个file_operations结构*/
static struct file_operations secong_key_fops =
                                              {
                                               .owner = THIS_MODULE,
                                               .open  = second_key_open,

                                               .read  = second_key_read,
                                               .release = second_key_close,     
                                              };
/*入口函数*/  
static int second_key_init(void)
{
    /*注册*/
    major = register_chrdev(0,"second_buttons",&secong_key_fops);
    /*创建类*/
    second_key_class = class_create(THIS_MODULE,"second_class");
    /*在second_key_class类下创建设备*/
    second_key_device =
    device_create(second_key_class,NULL,MKDEV(major,0),NULL,"second_device");
    /*初始化定时器*/
    init_timer(&key_timer);
    key_timer.function = key_timer_function;
    /*启动定时器*/
    add_timer(&key_timer);
    return 0;
}
/*超时处理函数*/
void key_timer_function(unsigned long data)
{
   struct pindec * pindesc = irq_dec;
    /*获取引脚值*/
   unsigned long pinval = s3c2410_gpio_getpin(pindesc->pin);
    /*松开时*/
   if(pinval)
       key_val  = pindesc->val;
   /*按下时*/
   else
       key_val = pindesc->val|0x80;
   /*中断事件标志置1,唤醒*/
   en_press = 1;
   wake_up_interruptible(&button_waitq);
}
/*出口函数*/
static void second_key_exit(void)
{
   /*注销*/
   unregister_chrdev(major,"second_buttons");
   /*注销设备*/
   device_unregister(second_key_device);
   /*销毁类*/
   class_destroy(second_key_class);
   /*删除定时器*/
   del_timer(&key_timer);
}
/*修饰*/
module_init(second_key_init);
module_exit(second_key_exit);
MODULE_LICENSE("GPL");



测试程序:

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
void main(int argc,char **argv)
{
     unsigned long key_val;
     int fd;
     fd = open("/dev/second_device",O_RDWR);
     if(fd < 0)
            printf("can't open!");
     while(1)
    {
            read(fd,&key_val,1);
            printf("key_val = 0x%x\n",key_val);
    }
}



测试:

1.加载驱动程序,利用insmod.

2.运行驱动的测试程序,

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表