s3c2410按键驱动完整版Word文档下载推荐.docx
《s3c2410按键驱动完整版Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《s3c2410按键驱动完整版Word文档下载推荐.docx(13页珍藏版)》请在冰豆网上搜索。
//构建一个结构体,用来描述中断管脚
structfspin{
intirq;
intpin;
char*name;
intnum;
introw_input;
introw_output;
intint_put;
intkey_val;
staticstructfspinfspin_desc[4]={
{IRQ_EINT0,S3C2410_GPF0,"
row0"
0,S3C2410_GPF0_INP,S3C2410_GPF0_OUTP,S3C2410_GPF0_EINT0},
{IRQ_EINT2,S3C2410_GPF2,"
row1"
1,S3C2410_GPF2_INP,S3C2410_GPF2_OUTP,S3C2410_GPF2_EINT2},
{IRQ_EINT11,S3C2410_GPG3,"
row2"
2,S3C2410_GPG3_INP,S3C2410_GPG3_OUTP,S3C2410_GPG3_EINT11},
{IRQ_EINT19,S3C2410_GPG11,"
row3"
3,S3C2410_GPG11_INP,S3C2410_GPG11_OUTP,S3C2410_GPG11_EINT19},
structpin_col{
intcol_input;
intcol_output;
staticstructpin_colcol_line[4]={
{S3C2410_GPE11,S3C2410_GPE11_INP,S3C2410_GPE11_OUTP},
{S3C2410_GPG6,S3C2410_GPG6_INP,S3C2410_GPG6_OUTP},
{S3C2410_GPE13,S3C2410_GPE13_INP,S3C2410_GPE13_OUTP},
{S3C2410_GPG2,S3C2410_GPG2_INP,S3C2410_GPG2_OUTP},
staticintkey_comfirm[4][4]={
{10,11,12,16},
{7,8,9,15},
{4,5,6,14},
{1,2,3,13},
/*构建异步通知注册函数用到的结构体*/
structfasync_struct*fsbuttons_fasync;
structfspin*cur_pin;
staticvoidset_col_output(void)
{
inti;
for(i=0;
i<
4;
i++){
s3c2410_gpio_cfgpin(col_line[i].pin,col_line[i].col_output);
s3c2410_gpio_setpin(col_line[i].pin,0);
}
}
staticvoidset_col_input(void)
s3c2410_gpio_cfgpin(col_line[i].pin,col_line[i].col_input);
s3c2410_gpio_pullup(col_line[i].pin,0);
//上拉
}
//void(*function)(unsignedlong);
staticirqreturn_tbutton_timer_fun(unsignedlongdata)
unsignedintval_sec;
introw;
intcol=-1;
if(!
cur_pin)
returnIRQ_NONE;
val_sec=s3c2410_gpio_getpin(cur_pin->
pin);
if(val_sec!
=cur_pin->
key_val)
row=cur_pin->
num;
/*将发生中断的引脚配置为输出低电平*/
s3c2410_gpio_cfgpin(cur_pin->
pin,cur_pin->
row_output);
s3c2410_gpio_setpin(cur_pin->
pin,0);
/*将kscan0-kscan3设为输入并拉高*/
set_col_input();
/*轮询列线,看哪个管脚为0,为0的那列保存起来*/
if(s3c2410_gpio_getpin(col_line[i].pin)==0)
col=i;
/*根据列线与行线保存键值*/
fs_buttons->
key_buttons=key_comfirm[row][col];
/*恢复*/
/*将列线恢复为输出,并且输出为0*/
set_col_output();
/*将产生中断的管脚,再次恢复为中断功能*/
pin,cur_pin->
int_put);
/*唤醒休眠的进程*/
wake_up_interruptible(&
(fs_buttons->
buttons_wq));
/*异步通知,发信号*/
kill_fasync(&
fsbuttons_fasync,SIGIO,POLLIN);
returnIRQ_HANDLED;
//typedefintirqreturn_t;
//#defineIRQ_NONE(0)//处理失败
//#defineIRQ_HANDLED
(1)//处理成功
//#defineIRQ_RETVAL(x)((x)!
=0)//无效的
staticirqreturn_tbuttons_irq_handler_fun(intirq,void*dev_id)
{
cur_pin=(structfspin*)dev_id;
/*获取管脚状态*/
cur_pin->
key_val=s3c2410_gpio_getpin(cur_pin->
/*有键按键按下*/
if(cur_pin->
key_val==0)
/*重载定时器*/
mod_timer(&
fs_buttons->
button_timer,jiffies+5);
returnIRQ_HANDLED;
staticintbuttons_open(structinode*inode,structfile*file)
inti;
intret=-1;
/*初始化设备*/
/*设置kscan0引脚为输出。
输出为0*/
/*注册中断,下降沿触发,中断名,中断id*/
for(i=0;
i++)
ret=request_irq(fspin_desc[i].irq,buttons_irq_handler_fun,IRQF_TRIGGER_FALLING,fspin_desc[i].name,&
fspin_desc[i]);
/*初始化定时器*/
init_timer(&
button_timer);
button_timer.expires=jiffies+5;
button_timer.function=(void*)button_timer_fun;
/*加载定时器*/
add_timer(&
/*初始化等待队列头*/
init_waitqueue_head(&
buttons_wq);
return0;
staticssize_tbuttons_read(structfile*filp,char__user*buf,size_tcount,loff_t*opps)
intret;
/*1.如果没有按键,而且应用程序是以非阻塞方式打开,就直接返回*/
if((fs_buttons->
key_buttons==0)&
&
(filp->
f_flags&
O_NONBLOCK))
return0;
/*1.如果没有键值key_buttons=0,则休眠*/
wait_event_interruptible(fs_buttons->
buttons_wq,fs_buttons->
key_buttons);
/*2.如果有键值,将键值返回用户空间*/
/*如果拷贝成功则返回0,否则返回剩下的没有拷贝完的字节数*/
ret=copy_to_user(buf,&
key_buttons,count);
key_buttons=0;
//键值清0
return1;
staticssize_tbuttons_write(structfile*file,constchar__user*buf,size_tcount,loff_t*opps)
/*异步通知*/
intbuttons_fasync(intfd,structfile*file,inton)
interror=0;
/*想办法将file中的某些参数拿出来,实际上就是在设置fsbuttons_fasync结构体*/
error=fasync_helper(fd,file,on,&
fsbuttons_fasync);
returnerror;
staticunsignedintbuttons_poll(structfile*file,structpoll_table_struct*wait)
intmask=0;
/*1.将进程挂入等待队列,但是并不休眠*/
poll_wait(file,&
buttons_wq),wait);
/*2.查看是否有事件*/
if(fs_buttons->
key_buttons)
mask|=POLLIN;
returnmask;
intbuttons_close(structinode*inode,structfile*file)
free_irq(fspin_desc[i].irq,&
structfile_operationsbuttons_fops={
.owner=THIS_MODULE,
.open=buttons_open,
.read=buttons_read,
.write=buttons_write,
.poll=buttons_poll,
.release=buttons_close,
.fasync=buttons_fasync,
/*构建和初始化fsbuttons_cdev结构体*/
staticvoidsetup_fsbuttons_cdev(void)
/*给cdev
结构体分配空间*/
buttons_cdev=cdev_alloc();
/*初始化*/
cdev_init(fs_buttons->
buttons_cdev,&
buttons_fops);
/*加载cdev*/
cdev_add(fs_buttons->
buttons_cdev,MKDEV(buttons_major,0),1);
staticint__initbuttons_init(void)
intdevno;
/*申请设备号,注册*/
if(buttons_major){
/*静态方式*/
devno=MKDEV(buttons_major,0);
register_chrdev_region(devno,1,"
buttons_driver"
);
}else{
/*动态方式*/
alloc_chrdev_region(&
devno,0,1,"
buttons_major=MAJOR(devno);
/*2.分配空间,
*GFP_KERNEL:
如果分配空间不成功,则会休眠
*/
fs_buttons=kmalloc(sizeof(fs_buttons),GFP_KERNEL);
/*构建cdev*/
setup_fsbuttons_cdev();
/*创建设备文件*/
buttons_class=class_create(THIS_MODULE,"
buttons"
class_device_create(fs_buttons->
buttons_class,NULL,MKDEV(buttons_major,0),NULL,"
staticvoid__exitbuttons_exit(void)
unregister_chrdev_region(MKDEV(buttons_major,0),1);
kfree(fs_buttons);
cdev_del(fs_buttons->
buttons_cdev);
class_device_destroy(fs_buttons->
buttons_class,MKDEV(buttons_major,0));
class_destroy(fs_buttons->
buttons_class);
module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("
GPL"
/*button_irq_test.c*/
stdio.h>
string.h>
#include<
sys/types.h>
sys/stat.h>
fcntl.h>
intmain(void)
intfd=-1;
intval=-1;
//fd=open("
/dev/buttons"
O_RDWR|O_NONBLOCK);
fd=open("
O_RDWR);
if(fd<
0){
perror("
open"
exit(-1);
while
(1){
ret=read(fd,&
val,4);
if(ret<
perror("
read"
exit(-1);
}
printf("
val=%d\n"
val);
/*button_poll_test.c*/
poll.h>
structpollfdpoll_fd[1];
poll_fd[0].fd=fd;
poll_fd[0].events=POLLIN;
ret=poll(poll_fd,1,5000);
if(ret>
0)
{
read(poll_fd[0].fd,&
printf("
val=%d\n"
elseif(ret==0)
timeout!
\n"
else
error!
/*button_fasync.c*/
unistd.h>
signal.h>
intfd;
/*1.实现信号处理函数*/
voidsignal_function(intsignum)
unsignedintval;
staticintcnt=0;
printf("
getsingal%d,cnt=%d\n"
signum,cnt++);
read(fd,&
intmain(intargc,char**argv)
intflags;
fd=open("
if(fd<
{
cannotopen/dev/buttons!
return-1;
/*2.将信号与信号处理函数绑定*/
signal(SIGIO,signal_function);
/*3.设置信号的拥有者为本进程*/
fcntl(fd,F_SETOWN,getpid());
//filp->
f_owner.pid=get_pid(pid);
/*4.设置为异步通知的模式*/
flags|=FASYNC;
fcntl(fd,F_SETFL,flags);
//调用到驱动中的fasync功能函数
while
(1)
/*做自己的事情*/
sleep(3);