您的位置:首页 > 运维架构 > Linux

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

2013-06-08 19:38 387 查看
[b]相关代码在资源中下载。

[/b]

按键利用定时器消抖:

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

2.初始化定时器,

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

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

/*初始化时一般设置,[b]expiresfunction,[b]data[/b]*/[/b]

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.运行驱动的测试程序,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐