矩阵键盘驱动开发实验报告Word文件下载.docx

上传人:b****6 文档编号:20212402 上传时间:2023-01-19 格式:DOCX 页数:14 大小:93.66KB
下载 相关 举报
矩阵键盘驱动开发实验报告Word文件下载.docx_第1页
第1页 / 共14页
矩阵键盘驱动开发实验报告Word文件下载.docx_第2页
第2页 / 共14页
矩阵键盘驱动开发实验报告Word文件下载.docx_第3页
第3页 / 共14页
矩阵键盘驱动开发实验报告Word文件下载.docx_第4页
第4页 / 共14页
矩阵键盘驱动开发实验报告Word文件下载.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

矩阵键盘驱动开发实验报告Word文件下载.docx

《矩阵键盘驱动开发实验报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《矩阵键盘驱动开发实验报告Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。

矩阵键盘驱动开发实验报告Word文件下载.docx

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!

PRINTK(revs_keyIOtherowis%dn,row);

GPFCON|=(0x0111*2)|(0x0110*2)|(0x019*2)|(0x018*2);

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!

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

staticintkeyDriver_open(structinode*inode,structfile*file)interr;

sema_init(&

readable,0);

err=kfifo_alloc(&

kbuffer,BUFFER_SIZE,GFP_KERNEL);

if(err!

=0)PRINTK(kfifoallocfailed!

return-ENOMEM;

/初始化io口/申请外部中断register_irqs();

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(&

key,sizeof(key)!

=0)ret=copy_to_user(buff,&

key,ret);

returnret;

staticintkeyDriver_release(structinode*inode,structfile*file)PRINTK(myDriverreleasecalled!

if(release_irqs()=0)PRINTK(irqfreesucceed!

kfifo_free(&

kbuffer);

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

while

(1)fd=open(devname,O_RDONLY);

if(fd0)perror(key44_enitopen:

);

exit

(1);

intlen;

unsignedcharkey;

len=read(fd,&

printf(KEYlen=%d,key=%dn,len,key);

close(fd);

2.运行结果:

七、实验总结通过本次矩阵键盘驱动开发实验我掌握了44键盘驱动的写法;

并且深入了解linux驱动架构。

还掌握了Linux下S3C2410IO端口驱动程序的编写方法;

知道了端口驱动程序的使用方法。

并对驱动进行了测试。

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

当前位置:首页 > 表格模板 > 调查报告

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

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