s3c2410按键驱动完整版.docx

上传人:b****8 文档编号:8887908 上传时间:2023-02-02 格式:DOCX 页数:13 大小:18.34KB
下载 相关 举报
s3c2410按键驱动完整版.docx_第1页
第1页 / 共13页
s3c2410按键驱动完整版.docx_第2页
第2页 / 共13页
s3c2410按键驱动完整版.docx_第3页
第3页 / 共13页
s3c2410按键驱动完整版.docx_第4页
第4页 / 共13页
s3c2410按键驱动完整版.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

s3c2410按键驱动完整版.docx

《s3c2410按键驱动完整版.docx》由会员分享,可在线阅读,更多相关《s3c2410按键驱动完整版.docx(13页珍藏版)》请在冰豆网上搜索。

s3c2410按键驱动完整版.docx

s3c2410按键驱动完整版

/*2410中断按键驱动

*基于s3c2410的16个按键驱动,采用中断的方式,实现了阻塞和非阻塞,并用定时*器进行了消抖处理消抖,也实现的异步通知,POLL机制,每个源文件我都加了比较*详细的注释。

各位刚刚学习ARM/Linux*驱动的同学可以参考。

*/

//button_irq_driver.c驱动源文件

//button_irq_test.c应用程序---按键测试(open可实现阻塞和非阻塞)

//button_poll_test.c应用程序---poll机制按键测试

//button_fasync.c应用程序---异步通知方式按键测试

/*button_irq_driver.c*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

staticunsignedintbuttons_major=0;

//本地结构体,表示一个按键

structfsbuttons_cdev{

structcdev*buttons_cdev;//按键设备结构体

structclass*buttons_class;//所属类

unsignedintkey_buttons;//按键管脚电?

1/0

wait_queue_head_tbuttons_wq;

structtimer_listbutton_timer;

};

staticstructfsbuttons_cdev*fs_buttons;

//构建一个结构体,用来描述中断管脚

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{

intpin;

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)

{

inti;

for(i=0;i<4;i++){

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)

{

inti;

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)

returnIRQ_NONE;

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的那列保存起来*/

for(i=0;i<4;i++){

if(s3c2410_gpio_getpin(col_line[i].pin)==0)

col=i;

}

/*根据列线与行线保存键值*/

fs_buttons->key_buttons=key_comfirm[row][col];

/*恢复*/

/*将列线恢复为输出,并且输出为0*/

set_col_output();

/*将产生中断的管脚,再次恢复为中断功能*/

s3c2410_gpio_cfgpin(cur_pin->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->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*/

set_col_output();

/*注册中断,下降沿触发,中断名,中断id*/

for(i=0;i<4;i++)

ret=request_irq(fspin_desc[i].irq,buttons_irq_handler_fun,IRQF_TRIGGER_FALLING,fspin_desc[i].name,&fspin_desc[i]);

/*初始化定时器*/

init_timer(&fs_buttons->button_timer);

fs_buttons->button_timer.expires=jiffies+5;

fs_buttons->button_timer.function=(void*)button_timer_fun;

/*加载定时器*/

add_timer(&fs_buttons->button_timer);

/*初始化等待队列头*/

init_waitqueue_head(&fs_buttons->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,&fs_buttons->key_buttons,count);

fs_buttons->key_buttons=0;//键值清0

return1;

}

staticssize_tbuttons_write(structfile*file,constchar__user*buf,size_tcount,loff_t*opps)

{

return0;

}

/*异步通知*/

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,&(fs_buttons->buttons_wq),wait);

/*2.查看是否有事件*/

if(fs_buttons->key_buttons)

mask|=POLLIN;

returnmask;

}

intbuttons_close(structinode*inode,structfile*file)

{

inti;

for(i=0;i<4;i++)

free_irq(fspin_desc[i].irq,&fspin_desc[i]);

return0;

}

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

结构体分配空间*/

fs_buttons->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_driver");

buttons_major=MAJOR(devno);

}

/*2.分配空间,

*GFP_KERNEL:

如果分配空间不成功,则会休眠

*/

fs_buttons=kmalloc(sizeof(fs_buttons),GFP_KERNEL);

/*构建cdev*/

setup_fsbuttons_cdev();

/*创建设备文件*/

fs_buttons->buttons_class=class_create(THIS_MODULE,"buttons");

class_device_create(fs_buttons->buttons_class,NULL,MKDEV(buttons_major,0),NULL,"buttons");

return0;

}

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*/

#include

#include

#include

#include

#include

intmain(void)

{

intfd=-1;

intval=-1;

intret=-1;

//fd=open("/dev/buttons",O_RDWR|O_NONBLOCK);

fd=open("/dev/buttons",O_RDWR);

if(fd<0){

perror("open");

exit(-1);

}

while

(1){

ret=read(fd,&val,4);

if(ret<0){

perror("read");

exit(-1);

}

printf("val=%d\n",val);

}

return0;

}

/*button_poll_test.c*/

#include

#include

#include

#include

#include

#include

intmain(void)

{

intfd=-1;

intval=-1;

intret=-1;

structpollfdpoll_fd[1];

//fd=open("/dev/buttons",O_RDWR|O_NONBLOCK);

fd=open("/dev/buttons",O_RDWR);

if(fd<0){

perror("open");

exit(-1);

}

poll_fd[0].fd=fd;

poll_fd[0].events=POLLIN;

while

(1){

ret=poll(poll_fd,1,5000);

if(ret>0)

{

read(poll_fd[0].fd,&val,4);

printf("val=%d\n",val);

}

elseif(ret==0)

{

printf("timeout!

\n");

}

else

{

printf("error!

\n");

}

}

return0;

}

/*button_fasync.c*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

intfd;

/*1.实现信号处理函数*/

voidsignal_function(intsignum)

{

unsignedintval;

staticintcnt=0;

printf("getsingal%d,cnt=%d\n",signum,cnt++);

read(fd,&val,4);

printf("val=%d\n",val);

}

intmain(intargc,char**argv)

{

intflags;

fd=open("/dev/buttons",O_RDWR);

if(fd<0)

{

printf("cannotopen/dev/buttons!

\n");

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);

}

return0;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 法学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1