Chinaunix首页 | 论坛 | 博客
  • 博客访问: 114097
  • 博文数量: 42
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: -5
  • 用 户 组: 普通用户
  • 注册时间: 2016-09-08 22:58
文章分类

全部博文(42)

文章存档

2012年(4)

2011年(11)

2010年(20)

2009年(7)

分类: LINUX

2011-08-22 15:44:50

很少写中断驱动,mark一个;

驱动程序

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


#define DEV_NAME "qjz_buttons"//DEV_NAME要与应用程序的open调用的NAME一样
static int buttons_major,buttons_minor=0;//定义设备号
static struct cdev buttons_cdev;//定义设备结构
static struct class *buttons_class;
static dev_t dev;

struct button_irq_desc
{
int irq;
int pin;
int pin_setting;
int number;
char *name;
};

static struct button_irq_desc button_irqs[ ]=
{
{IRQ_EINT1,S3C2410_GPF1,S3C2410_GPF1_EINT1,0,"KEY1"},
{IRQ_EINT4,S3C2410_GPF4,S3C2410_GPF4_EINT4,1,"KEY2"},
{IRQ_EINT2,S3C2410_GPF2,S3C2410_GPF2_EINT2,2,"KEY3"},
{IRQ_EINT0,S3C2410_GPF0,S3C2410_GPF0_EINT0,3,"KEY4"},
};
static volatile int key_values[]={0,0,0,0};
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;

static irqreturn_t buttons_interrupt(int irq,void *dev_id)
{
struct button_irq_desc *button_irqs=(struct button_irq_desc *)dev_id;
int up = s3c2410_gpio_getpin(button_irqs->pin);
if(!up)
{
key_values[button_irqs->number]=(button_irqs->number+1);
}
ev_press = 1;
wake_up_interruptible(&button_waitq);
return IRQ_RETVAL(IRQ_HANDLED);
}

static int buttons_open(struct inode *inode,struct file *filp)
{
int i,err;
unsigned long irq_type;
irq_type=ioread32(S3C2410_EXTINT0);//设置中断类型为上升沿
irq_type&=~(3<<1 | 3<<5 | 3<<9 | 3<<17 );
irq_type|=(3<<1 | 3<<5 | 3<<9 | 3<<17 );
iowrite32(irq_type,S3C2410_EXTINT0);

for(i = 0;i < 4; i++)
{
s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);
err = request_irq(button_irqs[i].irq, buttons_interrupt, NULL, button_irqs[i].name,(void*)&button_irqs[i]);
if(err)//成功返回值0,失败返回一个负的错误码
   break;
}
if(err)//失败就要释放已经注册成功的中断
{
i--;
for(;i>=0;i--)
{
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq,(void*)&button_irqs[i]);
}
return -EBUSY;
}
return 0;
}
static int buttons_close(struct inode *inode,struct file *file)
{
int i;
for(i=0;i<4;i++)
{
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq,(void*)&button_irqs[i]);
}
return 0;
}

static int buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
unsigned long err;
if(!ev_press)
{
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
else
wait_event_interruptible(button_waitq,ev_press);
}
ev_press = 0;
err=copy_to_user(buff,(const void*)key_values,count);
memset((void*)key_values,0,sizeof(key_values));
return err?-EFAULT:4;
}

static unsigned int buttons_poll(struct file *filp,poll_table *wait)
{
unsigned int mask = 0;
poll_wait(filp,&button_waitq,wait);
if(ev_press)
mask |=POLLIN|POLLRDNORM;
return mask;
}
static struct file_operations buttons_fops =
{
.owner = THIS_MODULE,
.open = buttons_open,
.release = buttons_close,
.read = buttons_read,
.poll = buttons_poll,
};


static int __init buttons_init(void)
{
int result;
if(buttons_major)
{
dev = MKDEV(buttons_major,buttons_minor);
result = register_chrdev_region(dev,1,DEV_NAME);
}
else
{
result = alloc_chrdev_region(&dev,buttons_minor,1,DEV_NAME);
buttons_major = MAJOR(dev);
}
if(result < 0)
{
printk(KERN_WARNING "buttons:can't get major %d\n",buttons_major);
return result;
}
else
{
printk(KERN_WARNING"registered ok\nbuttons_major = %d\n",buttons_major);
}

/*led_setup_cdev(&leds_cdev,0);*/
cdev_init(&buttons_cdev,&buttons_fops);
buttons_cdev.owner = THIS_MODULE;
buttons_cdev.ops = &buttons_fops;
result = cdev_add(&buttons_cdev,dev,1);
if(result < 0)
{
printk(KERN_WARNING"cdev_add failed!\n");
return result;
}
else
{
printk(KERN_WARNING"cdev_add is ok!!\n");
}
buttons_class = class_create(THIS_MODULE,DEV_NAME);
if(IS_ERR(buttons_class))
{
printk(KERN_ALERT"err:fail in buttons_class!\n");
return -1;
}
else
{
printk(KERN_WARNING"SUCCESS IN buttons_CLASS!\n");
}
class_device_create(buttons_class,NULL,MKDEV(buttons_major,0),NULL,DEV_NAME);
/*class_device_create(leds_class,NULL,dev,NULL,DEV_NAME);*/
printk(KERN_WARNING"buttons Module initialed!\n");
return 0;
}

static void __exit buttons_exit(void)
{
int devno = MKDEV(buttons_major,buttons_minor);
unregister_chrdev_region(devno,1);
cdev_del(&buttons_cdev);
class_device_destroy(buttons_class,devno);
class_destroy(buttons_class);
printk(KERN_WARNING"buttons module exit!\n");
}

module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("buttons device drver");
MODULE_AUTHOR("xxx");

应用程序

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

int main(void)
{
int i;
int buttons_fd;
int key_value[4];
buttons_fd=open("/dev/qjz_buttons",0);
if(buttons_fd < 0)
{
perror("open buttons fail");
exit(1);
}
for(;;)
{
fd_set reads;
int ret;
FD_ZERO(&reads);
FD_SET(buttons_fd,&reads);
ret = select(buttons_fd+1,&reads,NULL,NULL,NULL);
if(ret<0)
{
perror("select");
exit(1);
}
if(ret ==0)
{
printf("timeout\n");
}
else if(FD_ISSET(buttons_fd,&reads))
{
int ret=read(buttons_fd,key_value,sizeof(key_value));
printf("%d\n",ret);
//if(ret !=sizeof(key_value))
//{
//if(errno !=EAGAIN)//教程中这里是有的,但是不知道为什么每次读不出来按键值,屏蔽后,就可以读出来!如图!
//perror("read buttons\n");
//continue;
//}
//else
//{
for(i=0;i<4;i++)
{
if(key_value[i] !=0)
printf("K%d pressd,key value=0x%d\n",i+1,key_value[i]);}
continue;
// }

}
}
close(buttons_fd);
return 0;
}

奶奶的,怎么按一次有的时候会出现多次按下去的情况那?还是驱动的问题!感觉应该是中断的抖动造成的!关于如何去抖,要看看!

上面的应用程序用到了select,其实直接阻塞读,就是直接read也可以得到按键值!我觉得 select用在多输入多输出更有意义,也就是说用在多线程编程(例如聊天服务器里面的多点对多点,)。我不清楚用在这里是干什么!(貌似跟进程的效率有 关系)、直接阻塞读,就是进程来读,当没有读到数据就一直阻塞,一直到读取到数据才返回!

按照网上的资料说的是:Select 在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、 accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发 生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或 线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回 一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。

我觉得吧:像本例中在前面用到for循环,这样就会照成select的效率低下!他也是一直循环的去检查有没有读到数据。这岂不是跟阻塞读差不多啦!

阻塞read应用程序如下:

#include
#include
#include
#include
#include
#include
#include
#include
#include

int main(void)
{
int i;
int buttons_fd;
int key_value[4];
buttons_fd=open("/dev/qjz_buttons",0);
if(buttons_fd < 0)
{
perror("open buttons fail");
exit(1);
}
for(;;)
{
read(buttons_fd,key_value,sizeof(key_value));

for(i=0;i<4;i++)
{
if(key_value[i] !=0)
printf("K%d pressd,key value=0x%d\n",i+1,key_value[i]);}
continue;

}
close(buttons_fd);
return 0;
}

阅读(2566) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~