矩阵键盘驱动开发实验报告详解Word文档下载推荐.docx
- 文档编号:3624978
- 上传时间:2023-05-02
- 格式:DOCX
- 页数:17
- 大小:93.65KB
矩阵键盘驱动开发实验报告详解Word文档下载推荐.docx
《矩阵键盘驱动开发实验报告详解Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《矩阵键盘驱动开发实验报告详解Word文档下载推荐.docx(17页珍藏版)》请在冰点文库上搜索。
4×
4键盘一般采用行列扫描方法获取键值,为了进一步提高驱动程序的效率,这里结合外部中断获取键值。
GPF组IO端口都有外部中断功能,设置GPF0~3为上升沿触发外部中断,设置GPF4~7输出高电平,这样当有任何一个按键按下的时候,按键所在列对应的GPIO端口就会触发外部中断,由外部中断服务程序判断具体是哪个按键被按下。
2、外部中断
S3C2410处理器集成了外部中断功能,所谓外部中断是指处理器中具有触发中断功能GPIO,当GPIO出现电平变动时会触发中断。
触发中断的方式有多种,比如高电平触发低电平触发、上升沿触发,下降沿触发等。
S3C2410处理器中具有外部中断功能的GPIO每一位都可以单独设定中断触发方式,以满足不同的需要。
在4×
4键盘驱动中,使用上升沿沿触发中断的方式,当按键按下时外部中断被触发获得一次键值。
在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)
【功能】设置外部中断的中断触发方式
外部中断号
edge:
设置外部中断触发类型
pullup:
设置GPIO上拉或下拉
【函数原型】intdisable_irq(intirq)
【功能】禁止外部中断
【函数原型】intenable_irq(intirq)
【功能】使能外部中断
【函数原型】voidfree_irq(unsignedintirq,void*dev_id)
【功能】释放外部中断
dev_id:
在中断共享时会用到,用于标识不同的中断,这个参数要和request_irq
函数中的参数dev_id相同
3、4×
4键盘驱动架构
4键盘驱动通过全局数据缓冲队列实现在中断服务程序和读取函数之间数据传递,键值数据转移流程如图6.3所示。
五、实验步骤
1、实验指导书附带的源码中已经提供了键盘的驱动,驱动程序源码的路径为:
\drivers\gpf4×
4Keyboard,里面包含了键盘驱动程序和测试程序,可以使用下面的命令编译该驱动程序。
其中,-I参数后面的斜体部分需要换成实际的Linux源码路径。
arm-linux-gcc–c–I/root/kernel/include–D__KERNEL__s3c2410-gpf-keyboard.c
–os3c2410-gpf-keyboard.o//编译驱动
arm-linux-gcctest.c-otest//编译应用程序
2、执行上面的命令后,将生成的s3c2410-gpf-keyboard.o、test复制到目标板上,增加执行权限,然后使用下面的命令将驱动程序插入到目标Linux系统的内核中,由于在驱动程序中已经使用devfs为自己创建了设备文件节点,所以这里无需再使用mknod命令。
最后运行测试程序test,按下不同的键观察串口输出。
insmods3c2410-gpf-keyboard.o
chmod+xtest
./test
注意:
按键使用的GPF0与网络模块复用,应将网络模块跳线J8断开
六、实验内容
1.代码:
驱动程序:
/*=========================================================================
工程名称:
ex25_4MUL4keyboard_gpf
组成文件:
key44_driver.c
功能描述:
实现带中断及定时器的2*3键盘,通过管道缓存键值,知识点的综合应用
硬件连接:
GPF0~0与键盘行相连,GPF2~4与键盘列相连
维护记录:
2010-08-24v1.1addbydxh
=========================================================================*/
#include<
linux/module.h>
/*module_init()*/
linux/kernel.h>
/*printk()*/
linux/init.h>
/*__init__exit*/
linux/fs.h>
/*file_operation*/
asm/uaccess.h>
/*copy_to_user,copy_from_user*/
linux/device.h>
/*class,class_create,device_create等*/
linux/errno.h>
/*Errornumber*/
linux/delay.h>
/*mdelay,ndelay*/
asm/delay.h>
/*udelay*/
mach/regs-gpio.h>
/*S3C2410_GPGCON*/
linux/pci.h>
/*S3C24XX_VA_GPIO*/
linux/irq.h>
//set_irq_type,IRQ_TYPE_EDGE_FALLING
mach/irqs.h>
//IRQ_EINT2
linux/interrupt.h>
//request_irq,free_irq
linux/kfifo.h>
//#defineDEBUG//opendebugmessage
#ifdefDEBUG
#definePRINTK(fmt,arg...)printk(KERN_WARNINGfmt,##arg)
#else
#definePRINTK(fmt,arg...)printk(KERN_DEBUGfmt,##arg)
#endif
#defineDRIVER_NAME"
key44_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)//ADCstartorIntervalDelay
staticintMAJOR_NR=0;
/*DriverMajorNumber*/
staticintMINOR_NR=0;
//次设备起始号
structclass*my_class;
staticstructsemaphorereadable;
//定义信号量
#defineBUFFER_SIZE16//定义fifo的大小为16
staticstructkfifokbuffer;
//定义一个fifo变量
#defineINVALID_KEY0xFF
typedefunsignedcharKEYVALUE;
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%d\n"
err);
err=request_irq(KEY2_IRQ,&
KEY2"
(void*)1);
keyDriver_openint1%d\n"
err=request_irq(KEY3_IRQ,&
KEY3"
(void*)2);
keyDriver_openint2%d\n"
err=request_irq(KEY4_IRQ,&
KEY4"
(void*)3);
keyDriver_openint3%d\n"
}
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)
ininit_keyIO!
!
\n"
);
unsignedshortdata=0;
unsignedintconfig=0;
unsignedshortup=0;
GPFCON&
=~((0x03<
<
15*2)|(0x03<
14*2)|(0x03<
13*2)|(0x03<
12*2));
//清GPF12-15位
GPFCON&
11*2)|(0x03<
10*2)|(0x03<
9*2)|(0x03<
8*2));
//清GPF8-12位
GPFCON|=(0x02<
8*2)|(0x02<
9*2)|(0x02<
10*2)|(0x02<
11*2);
//gpf4-7设置为输出
GPFCON|=(0x01<
15*2)|(0x01<
14*2)|(0x01<
13*2)|(0x01<
12*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)|(0x01<
1)|(0x01<
2)|(0x01<
3)|(0x01<
4)|(0x01<
5)|(0x01<
6)|(0x01<
7));
GPFUP&
=~((0x01<
8)|(0x01<
9)|(0x01<
10)|(0x01<
11)|(0x01<
12)|(0x01<
13)|(0x01<
14)|(0x01<
15));
GPFDAT&
data=GPFDAT;
config=GPFCON;
up=GPFUP;
[init_keyIO]datais0x%x;
configis%x;
upis%x"
data,config,up);
staticvoidrevs_keyIO(introw)
inrevs_keyIO!
[revs_keyIO]therowis%d\n"
row);
=~((0x03<
GPFCON|=((0x01<
11*2)|(0x01<
10*2)|(0x01<
9*2)|(0x01<
GPFUP|=(0x01<
11);
GPFDAT|=(0x01<
11)|(0x01<
9)|(0x01<
8);
GPFDAT=~(0x01<
row);
//udelay(100);
staticconstKEYVALUEkeyMap[][0x10]={
{INVALID_KEY,0x01,0x05,INVALID_KEY,0x09,INVALID_KEY,INVALID_KEY,INVALID_KEY,0x0D,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY},
{INVALID_KEY,0x02,0x06,INVALID_KEY,0x0A,INVALID_KEY,INVALID_KEY,INVALID_KEY,0x0E,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY},
{INVALID_KEY,0x03,0x07,INVALID_KEY,0x0B,INVALID_KEY,INVALID_KEY,INVALID_KEY,0x0F,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY},
{INVALID_KEY,0x04,0x08,INVALID_KEY,0x0C,INVALID_KEY,INVALID_KEY,INVALID_KEY,0x10,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY,INVALID_KEY},
};
staticKEYVALUEkey_scan(introw)
intline=0;
revs_keyIO(row);
line=data>
>
12;
line=%d!
line);
returnkeyMap[row][line];
/*theinterruptdealfunction*/
staticirqreturn_tkey44_irqsrv(intirq,void*dev_id)
KEYVALUEkey;
inirqsrv!
close_irqs();
//关外部中断
row=%d!
(int)dev_id);
key=key_scan((int)dev_id);
[key44_irqsrv]keyvalueis%d\n"
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;
if(down_interruptible(&
readable)!
=0)
return0;
if(kfifo_len(&
kbuffer)>
=sizeof(key))
ret=count>
sizeof(key)?
sizeof(key):
count;
if(kfifo_out(&
kbuffer,&
key,sizeof(key))!
ret=copy_to_user(buff,&
key,ret);
returnret;
staticintkeyDriver_release(structinode*inode,structfile*file)
myDriverreleasecalled!
if(release_irqs()==0)
irqfreesucceed!
kfifo_free(&
kbuffer);
/*DriverOperationstructure*/
staticstructfile_operationskeyDriver_fops={
.owner=THIS_MODULE,
.read=keyDriver_read,
.open=keyDriver_open,
.release=keyDriver_release,
staticint__initmyModule_init(void)
keyDriver_init\n"
/*Driverregister*/
MAJOR_NR=register_chrdev(MAJOR_NR,DRIVER_NAME,&
keyDriver_fops);
if(MAJOR_NR<
0)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 矩阵 键盘 驱动 开发 实验 报告 详解