矩阵键盘驱动开发实验报告.docx
- 文档编号:7117470
- 上传时间:2023-01-19
- 格式:DOCX
- 页数:14
- 大小:93.66KB
矩阵键盘驱动开发实验报告.docx
《矩阵键盘驱动开发实验报告.docx》由会员分享,可在线阅读,更多相关《矩阵键盘驱动开发实验报告.docx(14页珍藏版)》请在冰豆网上搜索。
矩阵键盘驱动开发实验报告矩阵键盘驱动开发实验报告实验报告书实验名称:
矩阵键盘驱动开发实验专业班级:
学号:
姓名:
联系电话:
指导老师:
实验时间:
2014年11月13日计算机学院计算机科学与技术一、实验目的1、掌握44键盘驱动的写法;2、深入了解linux驱动架构。
二、实验设备1、装有Linux系统或装有Linux虚拟机的PC机一台;2、凌阳ARM9嵌入式实验箱SP-32AM11A一台;3、S3C2410CPU核心板一块;4、本实验用到实验箱的模块有:
S3C2410CPU板模块、44键盘模块。
三、实验要求1、实现功能:
编写44键盘驱动,并将键值通过控制台打印出来;2、实验现象:
每个键值通过控制台打印出来。
四、实验原理1、硬件原理本实验箱采用GPF07连接44键盘,其中GPF03与K1K4连接,GPF47与KAKD连接,分别用于控制44键盘的纵列和横列。
硬件连接如图6.2所示。
44键盘一般采用行列扫描方法获取键值,为了进一步提高驱动程序的效率,这里结合外部中断获取键值。
GPF组IO端口都有外部中断功能,设置GPF03为上升沿触发外部中断,设置GPF47输出高电平,这样当有任何一个按键按下的时候,按键所在列对应的GPIO端口就会触发外部中断,由外部中断服务程序判断具体是哪个按键被按下。
2、外部中断S3C2410处理器集成了外部中断功能,所谓外部中断是指处理器中具有触发中断功能GPIO,当GPIO出现电平变动时会触发中断。
触发中断的方式有多种,比如高电平触发低电平触发、上升沿触发,下降沿触发等。
S3C2410处理器中具有外部中断功能的GPIO每一位都可以单独设定中断触发方式,以满足不同的需要。
在44键盘驱动中,使用上升沿沿触发中断的方式,当按键按下时外部中断被触发获得一次键值。
在linux系统中对外部中断提供了比较好的支持,可以通过以下的函数设置外部中断。
【函数原型】intrequest_irq(unsignedintirq,void(*handler)(int,void*,structpt_regs*),unsignedlongirq_flags,constchar*devname,void*dev_id)【功能】申请中断【参数】irq:
要申请的硬件中断号handler:
向系统登记的中断处理函数,当中断发生时,系统调用这个函数irqflags:
中断处理的属性,若设置了SA_INTERRUPT,则表示中断处理函数是快速处理函数;若设置为SA_SHIRQ则表示多个设备共享中断devname:
设备标识字符串dev_id在中断共享时用到,用于标识不同的中断响应。
【返回值】成功返回0,失败返回错误码【函数原型】intset_external_irq(intirq,intedge,intpullup)【功能】设置外部中断的中断触发方式【参数】irq:
外部中断号edge:
设置外部中断触发类型pullup:
设置GPIO上拉或下拉【返回值】成功返回0,失败返回错误码【函数原型】intdisable_irq(intirq)【功能】禁止外部中断【参数】irq:
外部中断号【返回值】成功返回0,失败返回错误码【函数原型】intenable_irq(intirq)【功能】使能外部中断【参数】irq:
外部中断号【返回值】成功返回0,失败返回错误码【函数原型】voidfree_irq(unsignedintirq,void*dev_id)【功能】释放外部中断【参数】irq:
外部中断号dev_id:
在中断共享时会用到,用于标识不同的中断,这个参数要和request_irq函数中的参数dev_id相同【返回值】成功返回0,失败返回错误码3、44键盘驱动架构44键盘驱动通过全局数据缓冲队列实现在中断服务程序和读取函数之间数据传递,键值数据转移流程如图6.3所示。
五、实验步骤1、实验指导书附带的源码中已经提供了键盘的驱动,驱动程序源码的路径为:
driversgpf44Keyboard,里面包含了键盘驱动程序和测试程序,可以使用下面的命令编译该驱动程序。
其中,-I参数后面的斜体部分需要换成实际的Linux源码路径。
arm-linux-gcccI/root/kernel/includeD_KERNEL_s3c2410-gpf-keyboard.cos3c2410-gpf-keyboard.o/编译驱动arm-linux-gcctest.c-otest/编译应用程序2、执行上面的命令后,将生成的s3c2410-gpf-keyboard.o、test复制到目标板上,增加执行权限,然后使用下面的命令将驱动程序插入到目标Linux系统的内核中,由于在驱动程序中已经使用devfs为自己创建了设备文件节点,所以这里无需再使用mknod命令。
最后运行测试程序test,按下不同的键观察串口输出。
insmods3c2410-gpf-keyboard.ochmod+xtest./test注意:
按键使用的GPF0与网络模块复用,应将网络模块跳线J8断开六、实验内容1.代码:
驱动程序:
/*=工程名称:
ex25_4MUL4keyboard_gpf组成文件:
key44_driver.c功能描述:
实现带中断及定时器的2*3键盘,通过管道缓存键值,知识点的综合应用硬件连接:
GPF00与键盘行相连,GPF24与键盘列相连维护记录:
2010-08-24v1.1addbydxh=*/#include/*module_init()*/#include/*printk()*/#include/*_init_exit*/#include/*file_operation*/#include/*copy_to_user,copy_from_user*/#include/*class,class_create,device_create等*/#include/*Errornumber*/#include/*mdelay,ndelay*/#include/*udelay*/#include/*S3C2410_GPGCON*/#include/*S3C24XX_VA_GPIO*/#include/set_irq_type,IRQ_TYPE_EDGE_FALLING#include/IRQ_EINT2#include/request_irq,free_irq#include/#defineDEBUG/opendebugmessage#ifdefDEBUG#definePRINTK(fmt,arg.)printk(KERN_WARNINGfmt,#arg)#else#definePRINTK(fmt,arg.)printk(KERN_DEBUGfmt,#arg)#endif#defineDRIVER_NAMEkey44_eint/#defineKEY1_IRQIRQ_EINT0/#defineKEY2_IRQIRQ_EINT1/#defineKEY3_IRQIRQ_EINT2/#defineKEY4_IRQIRQ_EINT3#defineKEY1_IRQIRQ_EINT16#defineKEY2_IRQIRQ_EINT17#defineKEY3_IRQIRQ_EINT18#defineKEY4_IRQIRQ_EINT19#defineGPFCON(*(volatileunsignedlong*)S3C2410_GPGCON)/ADCcontrol#defineGPFDAT(*(volatileunsignedlong*)S3C2410_GPGDAT)/ADCtouchscreencontrol#defineGPFUP(*(volatileunsignedlong*)S3C2410_GPGUP)/ADCstartorIntervalDelaystaticintMAJOR_NR=0;/*DriverMajorNumber*/staticintMINOR_NR=0;/次设备起始号structclass*my_class;staticstructsemaphorereadable;/定义信号量#defineBUFFER_SIZE16/定义fifo的大小为16staticstructkfifokbuffer;/定义一个fifo变量#defineINVALID_KEY0xFFtypedefunsignedcharKEYVALUE;staticirqreturn_tkey44_irqsrv(intirq,void*dev_id);/*requestirqs*/staticvoidregister_irqs(void)interr=0;err=request_irq(KEY1_IRQ,&key44_irqsrv,IRQF_DISABLED,KEY1,(void*)0);PRINTK(nkeyDriver_openint0%dn,err);err=request_irq(KEY2_IRQ,&key44_irqsrv,IRQF_DISABLED,KEY2,(void*)1);PRINTK(keyDriver_openint1%dn,err);err=request_irq(KEY3_IRQ,&key44_irqsrv,IRQF_DISABLED,KEY3,(void*)2);PRINTK(keyDriver_openint2%dn,err);err=request_irq(KEY4_IRQ,&key44_irqsrv,IRQF_DISABLED,KEY4,(void*)3);PRINTK(keyDriver_openint3%dn,err);staticintrelease_irqs(void)free_irq(KEY1_IRQ,(void*)0);free_irq(KEY2_IRQ,(void*)1);free_irq(KEY3_IRQ,(void*)2);free_irq(KEY4_IRQ,(void*)3);return0;/*opentheirq_eint*/staticvoidopen_irqs(void)enable_irq(KEY1_IRQ);enable_irq(KEY2_IRQ);enable_irq(KEY3_IRQ);enable_irq(KEY4_IRQ);/*closetheirq_eint*/staticvoidclose_irqs(void)disable_irq_nosync(KEY1_IRQ);disable_irq_nosync(KEY2_IRQ);disable_irq_nosync(KEY3_IRQ);disable_irq_nosync(KEY4_IRQ);staticvoidinit_keyIO(void)PRINTK(ininit_keyIO!
n);unsignedshortdata=0;unsignedintconfig=0;unsignedshortup=0;GPFCON&=(0x0315*2)|(0x0314*2)|(0x0313*2)|(0x0312*2);/清GPF12-15位GPFCON&=(0x0311*2)|(0x0310*2)|(0x039*2)|(0x038*2);/清GPF8-12位GPFCON|=(0x028*2)|(0x029*2)|(0x0210*2)|(0x0211*2);/gpf4-7设置为输出GPFCON|=(0x0115*2)|(0x0114*2)|(0x0113*2)|(0x0112*2);set_irq_type(KEY1_IRQ,IRQ_TYPE_EDGE_FALLING);set_irq_type(KEY2_IRQ,IRQ_TYPE_EDGE_FALLING);set_irq_type(KEY3_IRQ,IRQ_TYPE_EDGE_FALLING);set_irq_type(KEY4_IRQ,IRQ_TYPE_EDGE_FALLING);/GPFUP&=(0x01)|(0x011)|(0x012)|(0x013)|(0x014)|(0x015)|(0x016)|(0x017);GPFUP&=(0x018)|(0x019)|(0x0110)|(0x0111)|(0x0112)|(0x0113)|(0x0114)|(0x0115);GPFDAT&=(0x0112)|(0x0113)|(0x0114)|(0x0115);data=GPFDAT;config=GPFCON;up=GPFUP;PRINTK(init_keyIOdatais0x%x;configis%x;upis%x,data,config,up);staticvoidrevs_keyIO(introw)PRINTK(inrevs_keyIO!
n);PRINTK(revs_keyIOtherowis%dn,row);GPFCON&=(0x0315*2)|(0x0314*2)|(0x0313*2)|(0x0312*2);GPFCON&=(0x0311*2)|(0x0310*2)|(0x039*2)|(0x038*2);GPFCON|=(0x0111*2)|(0x0110*2)|(0x019*2)|(0x018*2);GPFUP&=(0x0112)|(0x0113)|(0x0114)|(0x0115);GPFUP|=(0x018)|(0x019)|(0x0110)|(0x0111);GPFDAT|=(0x0111)|(0x0110)|(0x019)|(0x018);GPFDAT=(0x0112;PRINTK(line=%d!
n,line);returnkeyMaprowline;/*theinterruptdealfunction*/staticirqreturn_tkey44_irqsrv(intirq,void*dev_id)KEYVALUEkey;PRINTK(inirqsrv!
n);close_irqs();/关外部中断PRINTK(row=%d!
n,(int)dev_id);key=key_scan(int)dev_id);PRINTK(key44_irqsrvkeyvalueis%dn,key);if(key!
=INVALID_KEY)kfifo_in(&kbuffer,&key,sizeof(key);up(&readable);udelay(1000);init_keyIO();open_irqs();return0;staticintkeyDriver_open(structinode*inode,structfile*file)interr;sema_init(&readable,0);err=kfifo_alloc(&kbuffer,BUFFER_SIZE,GFP_KERNEL);if(err!
=0)PRINTK(kfifoallocfailed!
n);return-ENOMEM;init_keyIO();/初始化io口/申请外部中断register_irqs();return0;staticintkeyDriver_read(structfile*filp,char_user*buff,size_tcount,loff_t*offp)intret=0;KEYVALUEkey;if(down_interruptible(&readable)!
=0)return0;if(kfifo_len(&kbuffer)=sizeof(key)ret=countsizeof(key)?
sizeof(key):
count;if(kfifo_out(&kbuffer,&key,sizeof(key)!
=0)ret=copy_to_user(buff,&key,ret);returnret;staticintkeyDriver_release(structinode*inode,structfile*file)PRINTK(myDriverreleasecalled!
n);close_irqs();if(release_irqs()=0)PRINTK(irqfreesucceed!
n);kfifo_free(&kbuffer);return0;/*DriverOperationstructure*/staticstructfile_operationskeyDriver_fops=.owner=THIS_MODULE,.read=keyDriver_read,.open=keyDriver_open,.release=keyDriver_release,;staticint_initmyModule_init(void)PRINTK(keyDriver_initn);/*Driverregister*/MAJOR_NR=register_chrdev(MAJOR_NR,DRIVER_NAME,&keyDriver_fops);if(MAJOR_NR0)unregister_chrdev(MAJOR_NR,DRIVER_NAME);device_destroy(my_class,MKDEV(MAJOR_NR,MINOR_NR);class_destroy(my_class);PRINTK(myModule_exitokn);return;module_init(myModule_init);module_exit(myModule_exit);MODULE_LICENSE(GPL);MODULE_AUTHOR(sunplus);用户程序:
#include#include#include#includeintmain(intargc,char*argv)char*devname=/dev/key44_eint;intfd;if(argc1)devname=argv1;printf(NO:
11203070314Name:
liyangn);printf(NO:
11203070314Name:
liyangn);while
(1)fd=open(devname,O_RDONLY);if(fd0)perror(key44_enitopen:
);exit
(1);intlen;unsignedcharkey;len=read(fd,&key,sizeof(key);printf(KEYlen=%d,key=%dn,len,key);close(fd);2.运行结果:
七、实验总结通过本次矩阵键盘驱动开发实验我掌握了44键盘驱动的写法;并且深入了解linux驱动架构。
还掌握了Linux下S3C2410IO端口驱动程序的编写方法;知道了端口驱动程序的使用方法。
并对驱动进行了测试。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 矩阵 键盘 驱动 开发 实验 报告