s3c2410按键驱动完整编辑版.docx
- 文档编号:23643582
- 上传时间:2023-05-19
- 格式:DOCX
- 页数:16
- 大小:18.43KB
s3c2410按键驱动完整编辑版.docx
《s3c2410按键驱动完整编辑版.docx》由会员分享,可在线阅读,更多相关《s3c2410按键驱动完整编辑版.docx(16页珍藏版)》请在冰豆网上搜索。
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;
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- s3c2410 按键 驱动 完整 编辑