BIOS入门之我见-输入

   上篇我们着重介绍项目上所需的显示方面的知识,既然谈到人机交互,总要有人对机器下达指令,所以本篇就讨论键盘输入方面的相关知识,以期读者能够从底层理解键盘输入全过程的处理,当然我们还要围绕这个小程序xu继续展开完善,边完善边扩充知识:)

1.键盘的发展

    键盘的发展大致经历XT键盘到AT键盘再到PS2键盘(USB键盘不再本文讨论之列),这也是随着PC个人电脑发展阶段而演进的。 今天我们使用的键盘大约就是像是 AT 键盘和 PS2 键盘的合体:使用 PS2 键盘引入的小口,又支持 AT 扫描码(Scan Code Set2 )。为便于对比,笔者以图表相似展现,参考下图1。如果 读者有兴趣了解详情,可以参阅prostar的博文“ 键盘简史”连接如下:
http://blog.csdn.net/prostar/article/details/4144036


    图1 键盘发展与对比

2.键盘基础原理

2.1 键盘数据传输

     在最底层,键盘是有横纵矩阵组成的,这个跟51单片机里的矩阵键盘(matrix )是一致的。目前,键盘的具体实现形式多样,有机械接触式,电容式,轻触式等,但键盘基本上都是由单片机8048和按键组成,而主板端一般是8042键盘控制器用来与键盘链接,通常其被集成到Supper IO中或桥片里面。


    图2 键盘工作示意图
    8048负责检查哪个键按下,并把对应位置码(扫描码Scan code,这里分通码和断码)转换为传输码:1位起始位(0)+ 8位扫描码 + 1位奇偶校验 + 1位结束位。把并行的数码转变成串行的数据,通过键盘线传送到计算机主板端的键盘控制器 804 2,8042 再把串行数据转换成并行数据,提供给对应的IO端口,供CPU来使用。这里提到的IO端口,正是8042在X86系统里占用的 0x60和0x64 Port。


    图3 键盘IO寄存器功能

2.2 键盘数据的接收

    下面再说下CPU是怎样来用这个端口获取键盘输入的,有两种途径接收键盘控制器过来的数据,Polling和IRQ中断。

Polling轮询

     轮询就是CPU等待0x64状态寄存器Bit0被置起,然后读取IO端口0x64的数据字节,Polling便于理解和实现,但存在两个问题,1是正如所有的轮询方式的共同弊端,浪费了很多CPU的时间;2是当PS2控制器支持两个设备时,没有办法确定是哪个设备发过来的,除非是关闭其中一个或是其根本不支持发送数据过来。就如PS/2的键盘和鼠标同时接到系统PS/2控制器上,就不合适用这种方式。

IRQ中断 

    键盘的中断是IRQ1,当IRQ1触发时,触发CPU进行中断响应,调入对应的中断处理向量( INT 9h) 地址,该中断处理程序是由BIOS提供的,中断程序直接从IO端口0x60读取设备端发过来的数据,这里无需再判断状态寄存器的Bit0了,因为接收到IRQ1就代表键盘设备有数据发过来要处理,当读完IO端口数据后,向中断控制器发送EOI,从中断处理中返回。这不言而喻,会比Polling节省CPU的资源暂用,另外,对于两个以上的PS/2设备,其不同的IRQ已经将其区分,无需担心不知道是谁发过来的数据了。当然,仍然存在一种情况避免不了,就是当主机端需要给PS/2控制器发送发送命令并需要返回时,PS/2控制器会将数据放到IO端口中,但无法产生IRQ终端的,因为IRQ中断是由其下面的PS/2设备发过来的,因此,在这种情况下,只能用Polling轮询来解决,同时需要关闭所有的PS/2设备,以确保是PS/2控制器返回的数据,当然这样操作仅是在PS/2控制器初始化时才需要的,初始化完毕后无需再去Polling PS/2控制器返回的数据了。IRQ1对应的中断响应正是INT 9h,即向量号是9,为什么是INT 9h,可以参考PIC中断控制器的初始化相关介绍。


    图4 键盘中断处理过程

INT 9h

     用户按键,由8042发出IRQ1中断,BIOS调用INT 09中断服务程序。INT 09先从8042取得系统扫描码,然后根据扫描码值判断用户按键并作相应处理,最后通知中断控制器8259本次中断结束并实现中断返回。
若用户按下双态键(如:Caps Lock、Num Lock和Scroll Lock等),则在键盘上和BDA上相应LED指示灯的状态将发生改变;
若用户按下控制键(如:Ctrl、Alt和Shift等),则在BDA上相应的键盘标志位将发生改变;
若用户按下功能键(如:F1、F2、…等),再根据当前是否又按下控制键来确定其软件扫描码,并得到该按键所对应的ASCII码;
若用户按下字符键(如:A、1、+、…等),再根据当前是否又按下控制键来确定其软件扫描码,并得到该按键所对应的ASCII码;
若用户按下功能请求键(如:Print Screen等),则系统直接产生一个具体的动作。
对某些键或键的组合定义为单字节的ASCII码和扫描码,供系统中断INT 16H使用。
对某些键仅设置变量,反映其被按下或释放的状态。
对某些键或键的组合产生特殊操作。

2.3 键盘输入处理的封装

INT 16h

     为了方便上层软件或系统调用,除了必须的硬件终端服务程序外,Legacy BIOS还将键盘数据读取操作封装到BIOS软中断服务 INT 16h 中,为传统系统如DOS或Boot Loader等软件调用。
00H、10H —从键盘读入字符  03H —设置重复率
01H、11H —读取键盘状态  04H —设置键盘点击
02H、12H —读取键盘标志  05H —字符及其扫描码进栈
BIOS中断方便程序员不必了解硬件I/O接口的特性,可直接用INT指令参数,读取键盘按键信息。

INT 21h

    使用DOS操作比使用相应功能的BIOS操作更简易,而且对硬件的依赖性更少些。对一般的键盘操作,我们也可以使用INT 21H中断提供的键盘功能调用。  
01H — 从键盘输入一个字符并回显在屏幕上
06H — 读键盘字符
07H — 从键盘输入一个字符,不回显
08H — 从键盘输入一个字符,不回显,检测Ctrl_Break组合键
0AH — 输入字符到缓冲区
0BH — 读键盘状态
0CH — 清键盘缓冲区,并调用一种键盘功能 

C相关库函数

    C语言库函数也提供了一系列的键盘接收函数,如下表
    表1 C库提供的关于键盘输入的函数


 截至的目前为止,我们可以获取的键盘输入方法很多,总结一下: 
    1.通过C提供的库函数
    2.通过DOS中断INT 21h;
    3.调用BIOS软中断INT 16h;
    4.直接通过IO端口获取对应按键的Scan Code

2.4 BDA键盘数据缓冲区

BIOS在内存低端的BIOS数据存储区开设一个键盘缓冲区,其作用如下:
         (1)可以满足键盘实时输入要求。
         (2)适应随机访问的应用要求。
         (3)能容纳快速键盘输入要求。


    图5 BDA键盘数据缓冲区操作示意图
键盘缓冲区是一个先进先出的环形队列,0000:041Eh~ 0000:043Eh,16个字。不管是硬中断INT 9h还是软中断INT 16h都对这个BDA键盘数据区域进操作。INT 9h负责送入元素,而INT 16h负责取走元素。所谓的元素就是键盘的ASCII码和scan code.而这正好是INT 16h的function 0号功能返回的数据格式。

3. XU中的键盘处理方式

   前面提到过,对键盘的处理,BIOS已经封装过一层,DOS系统也提供对应的封装,而在C语言库函数也提供一些接口给到应用程序调用。在C库中,有一类专门为DOS等Legacy系统提供IBM兼容机的BIOS软中断调用的库<bios.h>, 当然,我也可以通过嵌汇编或调用<i86.h>提供的Intel中断调用接口函数int386(int86)直接指定要调用的中断号,在这里,我们用<bios.h>提供的_bios_keybrd实际上就是BIOS软中断提供的INT 16h服务。
   这里我们对通过_bios_keybrd 的_KEYBRD_READ 服务返回的数据稍作处理,因为这里返回的高字节是扫描码,低字节是ASCII码(如果有的话), 我们不妨采取如下策略,当输入的键盘有ASCII码时,就只保留低字节的ASCII码,当没有时,只保留高字节的扫描码。这样处理特殊功能键会方便些。至于对多种键盘输入可能的处理,用switch语句会明朗些。本文先只针对主页面菜单作输入处理,在按方向键时,菜单随之变化,来选择准备查询的系统信息。 如下为XU基本流程图


    图6 XU主框架流程图
具体实现请参考附件代码(本系列参考代码均可以在CSDN资源中找到),本文介绍键盘输入的原理和一些处理键盘输入的函数及中断,最后介绍了XU软件键盘处理的方法,虽然只是针对主界面的菜单项的键盘输入处理,后续各子功能模块的键盘处理方法类似,不再赘述。下一节,我们将开始介绍memory的读写方法,敬请期待。

4.参考资料

博文“ 键盘简史”  CSDN     http://blog.csdn.net/prostar/article/details/4144036
PS2键盘介绍    百度文库 
图解键盘的内部结构与原理    http://www.docin.com/p-832958.html
The PS/2 Keyboard Interface http://www.computer-engineering.org/
"8042" PS/2 Controller     http://wiki.osdev.org/"8042"_PS/2_Controller

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值