基于嵌入式Linux的键盘驱动设计
- 格式:doc
- 大小:126.50 KB
- 文档页数:3
291基于嵌入式Linux 的串口自定义键盘驱动开发张士林(江苏自动化研究所,江苏连云港222006)摘要:近年,随着科技发展,嵌入式已成为当今时代产业主流。
而嵌入式Linux 的优势使其成为主要的操作系统之一。
本文介绍了Linux 下驱动开发的一般模式,详细分析了基于串口通讯的自定义键盘驱动的开发方法,对嵌入式Linux 驱动开发有一定程度的指导作用。
关键词:嵌入式Linux 系统;串口键盘;驱动开发中图分类号:TP316.2文献标识码:A 文章编号:1673-1131(2019)12-0291-02Abstract:In recent years,with the development of science and technology,embedded technology has become the mainstream of the industry.The advantages of embedded Linux make it one of the main operating systems.This paper introduces the general mode of driver development under Linux,and analyzes in detail the development method of custom keyboard driver based on serial port communication.This paper has certain reference signification for the research and development of embedded system.Key words:embedded Linux system;serial keyboard driver;driver development0引言嵌入式系统(Embedded system ),是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”。
一、实验目的1. 理解键盘驱动程序的基本原理和设计流程。
2. 掌握键盘扫描矩阵的原理和实现方法。
3. 学习使用C语言进行键盘扫描驱动程序的开发。
4. 提高嵌入式系统开发能力和实际动手能力。
二、实验环境1. 开发平台:北邮嵌入式实验室提供的STM32开发板。
2. 编译工具:Keil uVision 5。
3. 实验软件:嵌入式Linux操作系统。
三、实验原理键盘扫描矩阵是一种常用的键盘输入方式,它通过行和列的交叉来检测按键的状态。
当按键被按下时,行和列的交叉点会形成一个特定的逻辑地址,该地址对应于键盘上的一个按键。
在嵌入式系统中,键盘驱动程序负责扫描键盘矩阵,识别按键状态,并将按键信息传递给上层应用程序。
本实验中,我们将使用C语言开发键盘驱动程序,实现以下功能:1. 初始化键盘硬件资源。
2. 扫描键盘矩阵,识别按键状态。
3. 将按键信息转换为ASCII码或其他编码格式。
4. 通过中断或轮询方式将按键信息传递给上层应用程序。
四、实验步骤1. 硬件连接将STM32开发板与键盘模块连接,确保键盘模块的行和列引脚正确连接到开发板的GPIO引脚。
2. 编写键盘驱动程序(1)初始化键盘硬件资源在驱动程序中,首先需要初始化键盘硬件资源,包括设置GPIO引脚的模式、上拉/下拉电阻等。
```cvoid keyboard_init(void) {// 设置GPIO引脚模式为输出GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// 设置GPIO引脚模式为输入__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}```(2)扫描键盘矩阵在驱动程序中,编写一个函数用于扫描键盘矩阵,识别按键状态。
第22卷第3期2008年6月江苏科技大学学报(自然科学版)Journa l o f Jiangsu U n i ve rsity o f Science and T echno l ogy(N a t ura l Sc i ence Ed iti on)V o1122N o13Jun.2008基于L inux的小键盘驱动及软硬键盘的映射韩斌1,2,刘伟民1,黄刚1,王士同2(1.江苏科技大学电子信息学院,江苏镇江212003)(2.江南大学信息工程学院,江苏无锡214122)摘要:研究了基于ARM9-L i nux的键盘驱动程序开发和利用Q t/Embedded界面开发工具的软键盘设计方法.在此基础上,实现了物理键盘和软键盘的映射,可通过物理键盘或软键盘对仪器进行控制,方便了用户操作.该方法已在某智能仪器的开发中成功应用.关键词:ARM-L Inux系统;键盘驱动;QT界面;键盘映射中图分类号:TP368文献标识码:A文章编号:1673-4807(2008)03-0053-04D esi gn of keyboard dri ver and keyboard m appi ng based on L i nuxHAN B i n1,2,LIU W ei m i n1,HUANG Gang1,WANG Sh itong2(1.School of E lectron i cs and Infor mati on,Jiangsu Un i versity of Scie n ce and Technol ogy,Zh e n jiang J i angs u212003,Ch i na)(2.S c hool of Infor m ation,Sou t h ern Yangts e Un i versity,W uxi J i angs u,214122,Ch i na)Abstract:A design m ethod of keyboard dri v er based on ARM9-Linux and so ft w are-based keyboar d by Q t/E m-bedded tools is introduced,On the basis,the physical keyboar d and so ft w are-based keyboard m appi n g are rea-l ized.The i n str um ent can be operated by usi n g the physical keyboar d or so ft w are-based keyboard conveniently. The m ethod has been successfully applied to the developm ent o f an i n telli g ent instru m en.tK ey words:AR M-L i n ux syste m;keyboar d dri v er;QT i n terface;keyboard m app i n g0引言随着计算机技术、机械制造技术和自动化技术的紧密结合,电子测量技术和电子测量仪器产生了新概念和新发展趋势.仪器的性能更加优异,测量性能更加强大,仪器的测量精度、灵敏度、范围都达到了前所未有的高度[1].特别是近年来,嵌入式技术的快速发展,由工业控制计算机完成的许多功能现在都可以移植到嵌入式系统上实现,而且性能更稳定,成本更低廉,更能符合工业现场的要求,嵌入式系统丰富的软硬件资源、便捷的开发手段吸引了越来越多的测量仪器基于嵌入式系统进行研制开发[2-4].文中设计了一个基于ARM-L i n ux系统的智能测量仪器的键盘控制模块,采用614寸触摸屏和自制小键盘,在编写键盘驱动程序的基础上,实现了物理小键盘与触摸屏软键盘的映射.1系统的硬件平台与软件平台嵌入式系统是整个测量仪器的核心,包括硬件部分和软件部分:硬件部分计采用Sa m sung公司的处理器S3C2410,内部集成ARM公司的ARM920T微处理器,最高主频达203MH z,扩展了64M、32位FLAS H和64M、32位SDRA M,外围资源丰富.软件系统采用Linux216内核的操作系统,它是源代码开放的嵌入式操收稿日期:2007-09-04作者简介:韩斌(1968-),男,汉族,江苏海安人,博士研究生,副教授,研究方向为嵌入式、图像处理.E-m ai:l cnhanb i n@yahoo.co m作系统,为各种外围模块提供了良好的支持.2 小键盘驱动的实现211原理图图1 硬件原理图F ig .1 B lock diagra m of hard w are图2 小键盘驱动模型图F ig .2 K eyboard -dr i ver m ode l 按键较少时,可以使用矩阵式小键盘,有键按下时,触发外部中断.其硬件原理图如图1所示.外部中断口E I N T11、E I N T19分别与GPG3、GPG11I/O 口复用;KSCAN0与GPE11口复用.外部中断口各由上拉电阻接313V 直流电压,工作在低电平触发模式.212 驱动编程当有键被按下时,触发一个外部中断.中断的处理函数中,使用内核打印函数进行信息提示,方便驱动程序的调试[5].小键盘驱动模型如图2所示.键盘的驱动程序可以分为如下几个部分:1)键盘驱动接口驱动程序提供一系列的接口供外部应用程序使用,驱动程序的接口都定义在str uct file_opera -ti o ns 结构体中.本文实现的驱动程序接口定义为:static str uct file_operati o ns key_fops={o wner : T H IS_MODULE ;open: key_open ;read : key_read ;re lease : key_release ;}2)驱动程序的初始化对GPGO /I 和GPFO /I 的相关寄存器进行配置,实现键盘初始化,并设置中断使能.如设置端口G 的控制寄存器:w ritel(read l(gpgcon)&0xffbfffb,f gpgcon),即把端口G 配置成输入口,且响应0号和2号外部中断.驱动程序要能够使用必须注册进内核,在L i n ux 下的系统调用register_chr dev(0,DE V I C E _NAME ,&key_f o ps)完成.同时要创建一个与键盘对应的设备文件才能够访问该设备,通过dev fs_mk_cdev(MKDE V (key M a -j o r ,KEYRA W _M I N OR),S_I FC HR |S_I R USR,"key /0")创建一个键盘设备,设备名称为//dev /key /00.由于键盘按键是通过中断来捕捉的,因此驱动程序中需要注册中断函数.中断注册使用request_irq(k ->irq_no ,&key_irq ,SA_I N TERRUPT ,"s3c2410-key",NULL)来完成,在中断函数中根据接受的中断号k->ir q_no 能够执行相应的中断处理例程&key_irq .3)中断服务函数.键盘中断被接收后,根据不同的按键转去执行相应的中断服务例程.4)驱动接口函数str uct file_operati o ns 结构体中,key_open()用于打开键盘设备,key_re lease()用于关闭键盘设备,key_read()实现了向用户空间传送I /O 口数据寄存器数值的功能,据此可判别是哪个按键被按下.在驱动程序中必须对这些接口进行实现.213 建立交叉开发环境并测试驱动1)安装交叉开发环境,使用cross-31312.bar .bz2生成ar m -li n ux -gcc 工具.2)配置内核,以模块方式添加键盘驱动.54江苏科技大学学报(自然科学版)2008年3)编译内核,生成key .ko 键盘驱动模块.4)挂载驱动模块:ins m od key .ko .5)交叉编译测试程序并下载运行./key_tes,t 以检测按键驱动程序是否可以正常工作.3 QT界面的软按键的实现图3 Q t /E 的实现结构F ig .3 Q t/E structure Qt/E 是挪威tr o lltech 公司专门针对嵌入式GU I 开发而设计的一个工具包.使用Q t/E 开发的应用程序界面清晰美观、操作方便[6].图3为Q t/E 的实现结构[7-8]:311 QT 开发环境的建立本文建立QT 开发环境使用Q t/Embedded 31317、Qt/Embed -ded 31317for X11两个软件包.Qt/Embedded 31317for X11软件包提供一个uic 工具和designer 开发工具;Q t/E m bedded 31317软件包主要是生成能够在开发平台上运行的Q t 库和q m ake 工具.在搭建QT 交叉开发环境时需要设置如下几个变量:QT2DI R 和QTED I R ,分别指向Q t/Embedded 31317for X11软件包和Q t/E m bedded 31317软件包.搭建步骤分为两步:1)编译Q t/E m bedded for X11生成u ic 工具# cd $QT2D I R# ./configure )no-x ft# m ake2)编译Q t/E m bedded 31317生成qt 交叉开发的库文件#./configure )xplatfor m linux-ar m -g++-no-x ft -no-qvfb-depths 8,16,32#m ake至此,QT 的开发环境搭建完毕,可以在$QTEDI R /bi n 目录下看到生成的qmake 、uic 等工具,$QTE -DI R /lib 目录下生成了在开发板上运行所需要的QT 库.在$QT2DI R /b i n 目录下得到desi g ner 集成开发环境.312 QT 界面软键盘设计在触摸屏中实现软按键,需要定义各按键的坐标、位置、名称等信息.本文软键盘中按键的设计使用QT 中的QPushButton 类定义.对于每一个按键所触发的动作采用QT 的信号和插槽机制来实现.例如:对于按钮pushbu tton 的单击(clicked)事件,它触发的动作写在函数action()里,通过connect(pushbutton ,SI G -NAL(clicked()),th is ,SLOT (action()))建立事件与动作的连接.按键的设计如下:m y m ain w indo w::m y m ainw indo w (QW i d get*paren,t const char*na m e):QD i a l o g(paren,t na m e){ b=ne w QPushButton("END",th is);b->set G eo m etry(485,390,100,45);b->set F ont(QFont("T i m es",18,QFon:t :Bold));connect(b3,SI G NAL(clicked()),this ,SLOT(m yex itsl o t()));}4 QT 界面按键与物理键盘按键的映射以上分别实现了物理按键和触摸屏软按键.下面以物理按键K1与触摸软按键b3的连接为例,介绍一种软、硬键盘的映射方法.物理键盘与软键盘的映射通过如下4步完成,如图4所示:1)打开键盘设备.vo i d my m a i n w i n dow ::init()55第3期 韩 斌等:基于L i nux 的小键盘驱动及软硬键盘的映射图4 软硬键盘映射流程图F ig .4 F l ow chart of so ft keyboard m app i ng {key_fd=open(KE Y _DEV,O_RDWR);}2)读取与按键相关I/O 口数据寄存器.read(key_fd ,(char *)&bu,f sizeof(buf))3)根据读取数据判断哪个物理按键被按下.if(buf==0x00bf){e m i:t :shutdo wn();,,;}当f 口数据寄存器为00bf 时,可以判断出是K1键按下,执行相应功能.4)发消息连接到与该物理键对应的软键的插槽中,触发软按键的插槽里的动作.通过物理键盘的按键触发对应软键的动作,从而实现两者的映射.connect(th is ,SI GNAL(shutdo wn()),th is ,SLOT(myex itslot()))connect()将shutdo w n 信号与b3软键的插槽myex itslot()相关联,这样当按下K1键后,系统自动调用软键b3的插槽,实现b3的相应动作,从而实现物理按键K1与触摸键b3的连接.其他按键的映射依次类推.5 结 论本文提出了物理键盘的驱动及触摸屏软键盘设计方法,并实现了物理小键盘与触摸屏软键盘的映射.物理键盘与触摸屏软键盘的映射,方便了用户操作.此方法已在某基于嵌入式系统的测量仪器中得到应用.参考文献(References)[1] 汪晓东.21世纪电子测量仪器及自动测试系统的新概念和新趋势[J].电子测量与仪器学报,2005,19(1):78-81.W ang X iaodong .N e w concept and ne w techno l ogy trend of e l ectronictest i nstru m ents and au t oma ti c test systems in 21century[J].Journal of E lectronicM easure m ent and Instru m ent ,2005,19(1):78-81.(i n Chi nese)[2] 杨晔,刘镇.嵌入式操作系统L C /O S Ò的移植和应用[J].华东船舶工业学院学报:自然科学版,2003,17(2):35-39.Y ang Y e ,L i u Zhen .Po rti ng and appli cati on of e mbedded operati on syste m L C /OS Ò[J].Journal of East Chi na Shi p building Instit ute :N atural Scie nce Ed ition ,2003,17(2):35-39.(i n Chi nese)[3] 陈峰,李滨滔,戈志华.基于S3C2410的嵌入式L inux 系统构建[J].现代电子技术,2007(24):55-60.Chen Feng ,L i B i ntao ,G e Zhi hua .Construc tion of the embedded L inux syste m based on S3C2410[J].M odern E lectron ic T echn i que ,2007(24):55-60.(in Ch i nese)[4] 杨建伟,杨燕翔.基于S3C2410处理器的L inux 移植[J].信息技术,2007(8):97-100,103.Y ang Ji an w e,i Y ang Y anx i ang .L i nux transplant based on the processor o f S3C2410[J].Infor m ation T echnology,2007(8):97-100,103.(i n Ch i nese)[5] 刘淼.嵌入式系统接口设计与L i nux 驱动程序开发[M ].北京:北京航空航天大学出版社,2006.L iuM i ao .Embedde d Syste m Interface D esi gn and Linux D river D evel opment [M ].Beiji ng :Beiji ng U nivers i ty of A eronauti cs and A stronauti cs Press ,2006.(i n Chi nese)[6] B l anchette G,Su mmerfieldM.C++GU I Q t3编程[M ].北京:北京航空航天大学出版社,2006.B l anchette G,Su mmerfieldM.C ++GUI Q t 3P rogra mm i ng [M ].Beiji ng :Beiji ng U ni ve rsity o f A eronautics and A stronauti cs P ress ,2006.(i n Ch i nese)[7] 王存健,张建正.嵌入式L i nux 下Q t/Embedded 的应用[J].计算机技术与发展,2006,16(11):179-181.W ang Cunji an ,Zhang Ji anz heng .A pplication of Q t/E m bedded on e m bedded L i nux[J].Co mputer T echnology an d D evelop-ment ,2006,16(11):179-181.(i n Chi nese)[8] 李杰,曹宇,朱坚,等.基于嵌入式L i nux 的矩阵键盘设计与实现[J].现代电子技术,2006,239(24):81-83.L i Ji e ,Cao Y u ,Zhu Ji an ,et a.l D esi gn and i m ple m ent of ma trix keyboard based on e mbedded L i nux[J].M odern E lectron ic T echn i que ,2006,239(24):81-83.(i n Ch i nese)(责任编辑:曹 莉)56江苏科技大学学报(自然科学版)2008年。
1 键盘驱动程序的设计随着电子信息技术飞速发展,嵌入式系统构成的各种设备得到了广泛的应用, 嵌入式Linux是一种开放源码、软实时、多任务的操作系统,是开发嵌入式产品的优秀操作系统平台,其中键盘是人机界面中人类监控计算机重要数据输入设备。
实现键盘有两种方法:一种是采用现有的一些芯片实现键盘扫描;二是用软件实现键盘扫描。
目前许多芯片可用来实现键盘扫描,但是键盘扫描的软件实现方法有助于缩减系统的重复开发成本, 而只需很少的CPU 开销。
嵌入式控制器的功能很强,可以充分利用这一资源。
本课题提出的键盘方案是以嵌入式Linu x和S3C2410A为软硬件平台, 通过测试,表明其具有良好的稳定性和实时性。
2 矩阵式键盘的结构与工作原理本课题采用矩阵键盘, 如图1所示。
四根行线四根列线组成 4 *4矩阵键盘, 分别用CPU 的4个GPIO口。
当有键按下,某个列GPI O 口电平被下拉从而产生下降沿, 触发中断。
其中按键行阵列必须提供上拉信号,列阵列加二极管,防止瞬间电流过大对GPI O口造成冲击。
图 1 矩阵键盘原理图.3 Linux键盘驱动简介在Linux中, 键盘驱动被划分成两层来实现。
上层是一个通用键盘抽象层, 下层则是硬件处理层, 主要对硬件进行直接的操作。
键盘驱动程序上层公共部分在driver /key-board . c里。
文件中最重要的是内核用EXPORT _SYM BOL这个宏导出的handle_scancode函数。
在这个文件中还定义了其它的几个回调函数,它们由键盘驱动程序中上层公共部分调用, 并且由底层硬件处理函数实现。
键盘驱动程序的底层硬件处理部分则根据不同硬件有不同实现。
4 键盘驱动程序的实现4 . 1 宏定义module init和module exit通过宏定义module init和module exit可以看出,驱动程序的入口从kd_ctrl_init( )开始。
当内核模块加载的时候, 默认调用module_ i nit( kd_c trl_init) ,在kd_ctr l_ i nit( )中将完成一些初始化工作, 主要如下:( 1) 把GPI O 口的起始虚拟地址映射到GPI O _BASE _PHY ( 0x1000b000),数据长度为0x400 : GPI O _ BASE = ( i nt) ioremap ( GPI O _ BASE _ P HY,0x400);( 2) 利用requeST_ irq函数将外设的中断服务例程挂载到外部中断处理程序中。
本系统中利用request_irq函数分别为4个列GPI O口申请中断资源, 分别占用了中断号1 、2 、3、4 。
其中i是中断号; kd_ctr l_irq是UCB1400的中断处理程序, kd_ctr l代表键盘设备名, MAGIC _DEVID是申请时告诉系统设备标志, 用于共享中断线。
返回值为0表示申请成功。
( 3) 通过函数m isc_reg ister注册一个键盘设备, 并分配主设备号和从设备号, 初始化一个环形队列以及定义一个键盘控制的数据结构。
其中包括键值、键的状态和长按标志。
应用程序对设备驱动的调用实际是对相应设备文件进行操作, 利用mknod命令将此节点与对应设备建立联系。
( 4) 通过init_ w a it queue_head(& sa ts . read _ w a it)初始化读信号量。
4 . 2 打开键盘设备应用程序打开设备文件时, 会调用驱动中的OPEN 函数, 此函数会对键盘所用到的行列GPI O 口进行配置。
打开的设备在内核中通过file结构进行标识, 内核使用file opreaTI ON ,通过上面的结构中设备文件操作结构的映射, 来调用驱动中的kd_c trl_open。
接下来要做的是:( 1) 通过se m a_ i n it( & kdc- > irq_w ait , 0)初始化在后面用来唤醒后台线程的信号量。
( 2) 调用初始化函数i n it_pxa_kdc( )来初始化GPI O口,具体是把行!的GPI O 口设为输出模式并设定值为0 , 把列!GPIO口设为中断模式,下降沿有效。
如下所示:re t = se t_kdc_gp i o( KDC_ROW _PINS , 1 , PI NS_MODE _OUT , 0) ;ret = set_kdc_gp i o ( KDC _COL _PI NS , 1 , PI NS _ MODE _FALLI NG_I NTTERUPT , 0);( 3) 以严格的串行方式执行任务的效率并不高, 如果把它们放在后台调度,不管是对它们的函数还是对终端用户进程都能得到较好的响应。
所以初始化GPIO口后,开启一个内核线程kd_ctrl_thread专门用于处理键盘事件, 其实也就是向系统申请了软硬件资源。
为了确保在该线程创建完成,使用co m pleti on ,在Linux内核中, co m pletion是一种简单的同步机制,利用co m pleti on机制可以使两个任务同步。
我们利用i n it_comp l e ti on(& kdc- > i n it_ex it)动态初始化一个线程创建信号量i n it_ex it , 以及用wa it_fo r_co m pleti on (& kdc- >i n it_ex it)来等待进程创建完成, 然后在进程创建结束后通过co m plete(& kdc- > i nit_ex it)确定事件已经完成即后台线程创建成功, 继续执行函数w ait_ for_ comp l e ti on之后的任务。
通过ret = kerne l_t h read( kd_c trl_ t hread , kdc , CLONE_FS |CLONE_FILES)创建后台线程。
4 . 3 等待键盘事件后台线程一旦创建和初始化完成, 就会进入一个无条件的for循环, 通过set _ task _ state ( tsk , TASK _ INTERRUPT IBLE) 将此线程推入可中断睡眠的队列,调用schedule ti m e ou t (H Z/100)来实现15毫秒的进程挂起。
此时让出CPU,直到中断事件来临或睡眠超过规定时间后再重新执行。
线程一旦被唤醒即按照顺序先利用set_kdc_gp io ( KDC _COL_PI NS , 1 , PI NS _MODE _ENABLEI NTERRUPT, 0) 使所有列GPI O 口中断, 接着调用down _ i nterrupti b l e ( & kdc- > irq _wa it): 该函数的作用是获得信号量irq_wa it , 把irq_ w a i t的值减掉 1 , 如果信号量irq_wa it的值非负, 就直接返回,如果获取失败键盘线程将以TASK_I NTERRUPTIBLE状态进入可中断睡眠,直到下次键盘事件利用信号量irq_ w a it唤醒此线程才能继续运行。
因此,驱动程序在没有按键按下时将阻塞自己的执行,不消耗任何的CPU资源。
4 . 4 键盘事件发生一旦有按键事件发生也就是产生一个中断, 则进入中断处理程序kd_ctr l _ irq( ), 在这个函数中所做的工作如图2。
图 2 中断处理程序kd_ ctrl_irq( )唤醒后台线程后,把列GPI O口中断禁止, 随即调用kd_ctrl_event( )进行处理键盘事件。
其中又调用pxa _kdc _scan( )进行键值的扫描: 设定4*4小键盘的所有行GPI O 口为输出状态,并设定它的值为1 ,而所有列GPIO口作为输入状态,然后采用逐行扫描的方法, 依次去读取四根列GPI O 口状态,如果某列GPIO 口电平为低, 就表示此行此列有键按下,根据行号和列号从对应的二维数组(也就是键值映射表)中找到该键的键值。
具体实现方法为: 先设第一行( GPI O7)为0 , 扫描列的值( GPI O3 、GPI O2 、GPI O1、GPI O0),如果其中一个列的值为0 , 比如GPI O3 , 则按下的键是Key _5。
扫描完列后,把第一行设为1。
第二行设为0 , 再次扫描所有列的值。
扫描结束后, 设定所有行( GPI O7 、GPI O6 、GPI O5 、GPI O4)的值为0 , 并且再次恢复所有列为中断方式,设定下降沿有效。
最后返回的是代表按键是否按下的参数pressure值。
得到此值以后,调用stati c i n line vo i d kd_c trl_ev t_add( struc t kd_ctrl* kdc , u8 pressure , u8 keyva l ue )函数把所得值保存在对应的结构中,并将其添加到事件队列中, 最后调用w ake_up_ i nterrupti ble( & kdc- > read _ w a it)利用信号量read_ w a it通知read程序到缓冲区读取新数据。
4 .5 应用程序读取键盘数据由于用户程序需要不断轮询设备,以查询是否有数据读取, 如果程序不处于休眠状态, 则将会占用很多CPU 的资源。
因此当没有触摸数据时, 就阻塞此任务。
此时用户空间则需要和内核同步, 代码会需要睡眠, 使用信号量是唯一的选择, 并且它适用于锁会被长时间持有的情况。
如果有一个任务试图获得一个已经被占用的信号量时,信号量会先将其中推进一个等待队列, 然后让其睡眠。
这时CPU 能重获自由, 从而可以执行其他代码。
当持有信号量的进程将信号量释放时, 处于等待队列中的那个任务将会被唤醒, 并获得该信号量。
等待队列是由等待某些事件发生的进程组成的简单链表。
内核用w ake_queue_head_t来表示等待队列。
等待队列可通过DECLARE _WAI TQUEUE ( )静态创建。
一旦上层用户程序进行读操作, 系统调用将通过kd_ctrl_read ( )函数来实现。
4 . 6 模块卸载当内核需要卸载本驱动程序时, 最后会从本函数退出。
此时通过modul e_ i nit( kd_ctrl_ i n it)函数需要将在驱动程序运行期间申请的系统资源全部释放掉,可以防止资源浪费。
5 结束语本文介绍的嵌入式Linux的一种矩阵小键盘, 成功实现了多键齐按和重复按键的功能, 已经用于手持嵌入式设备中, 实验证明性能稳定可靠。