操作系统实验日志DAY 7

一、 实验主要内容

(一) 获取按键编码

鼠标不动原因:
       设定不到位
目标:
       程序在按下一个后不结束,而是把所按键的编码在画面上显示出来。

【函数解析】

在这里插入图片描述

       注意看红框部分,这里io_out8(PIC0_OCW2, 0x61);,通知了PIC已经知道发生了IRQ1中断。执行这句话这周,PIC时刻监视IRQ1中断是否发生中断,这样按键输入才能由系统感知。

(二) 加快中断处理

【中断处理是什么】

       所谓中断处理,就是打断 cpu本来的工作,加塞要求进行处理。并在中断期间,不在接受别的中断。
       并不知道中断会在哪个瞬间到来,所以要先将按键的编码接收下来,保存在变量里,然后由HariMain偶尔去查看这个变量。如果发现这个数据,就把她显示出来。
       完成这样的设置之后,考虑到键盘输入时需要缓冲区,定义了一个结构体keybuf。其中flag变量用来表示这个缓冲区是否为空。

【理解HariMain部分函数】

       代码注释如下:
在这里插入图片描述

【测试运行】

现象:
       按下右ctrl键显示1D,松开显示9D。
原因:
       当按下右ctrl键时候,会产生两个字节的键码值“E0 1D”,松开之后会产生两个字节的键码值“E0 9D”。在一次产生两个字节键码值的情况下,因为键盘内部电路一次只能发送一个字节,所以一次按键就会产生两次中断,第一次中断发送E0,第二次中断发送1D。
比较:
       对于前面在a中,两次中断所发送的值都能收到,瞬间显示E0之后,接着又显示1D或9D。而在b中,HariMain函数在收到E0之前,又收到前一次按键产生的1D或9D,而这个字节就被舍弃了。

(三) 制作FIFO缓冲区

【int.c】

       首先我们来理解部分int函数
       keybuf.next的起始点是0,所以最初存储的数据是keybuf.data[0]。下一个数据是keybuf.data[1],接着是[2],以此类推,一共有32个存储位置。其中下一个存储位置用next管理。这样就会记住32个数据而不会溢出。但是为了保险,next值变成32后,就舍去不要。

【取数据程序】

        如果next不是0,说明至少有一个数据。最开始的一个书肯定是放在data[0]中,将这个数存入到变量i中去,这样数减少了一个,next-1。
        for循环的作用就是将数据存放的位置全部向前移送一个位置,如果不移送的话,下一次就不能从data[0]读入数据了。但是数据移送处理,在禁止中断的期间做会有问题。

(四) 改善FIFO缓冲区

基本思路:
       不仅要维护下一个要写入数据的位置,还要维护下一个读出数据的位置。这就好像数据读出位置在追着数据写入位置跑一样,这样做就不需要数据移送操作了。数据读出位置追上数据写入位置的时候,就相当于缓冲区为空,没有数据。但是这样,容易进入死胡同,比如缓冲区使用一段时间之后,下一个数据写入位置就会变成31,这时下一个数据读出的位置可能已经是29或者30。当写入位置变成32的时候,就走到死胡同,因为没有地方可以写数据了。
       我们只要将下一个数据写入位置和下一个数据读出位置都再置为0就行,就像转回去从头再来一样。
       我们对于下一个数据读出位置也做用样的处理,一旦到达32之后,就把她设置为0从头开始继续读取数据。这样32个字节的缓冲区就能一圈一圈不停的循环,只要不溢出就可以一直使用下去。

(五) 整理FIFO缓冲区

       鼠标只要稍微一动,就会连续发送3个字节的数据。首先我们要把结构做成如下这样:
       我们将缓冲区大小定义为可变的,总的字节数保存在变量size里面。变量free用于保存缓冲区里面没有数据的字节数。缓冲区的地址也保存下来,把他保存在变量buf里。p代表下一个数据写入地址(net_w),q代表下一个数据读出地址(next_r)。

【fifo.c的fifo8_int函数】

       fifo8_int是结构的初始化函数,用来设定各种初始值,也就是设定fifo8结构的地址已经与结构有关的各种参数。

【fifo.c的fifo8_put函数】

       fifo8_put是往FIFO缓冲区存储1字节信息的函数。用flags这一变量来记录是否溢出。分别用-1和0来表示溢出和没有溢出两种情况。

【fifo.c的fifo8_get函数】

       fifo_get函数是从FIFO缓冲区取出一个字节的函数。

【fifo.c的fifo8_status函数】

       用来调查缓冲区的状态。

(六) 鼠标

       给鼠标分配中断号IRQ12.处于初期状态的鼠标,不管是滑动操作还是点击操作都没有反应。我们来看下面的两个函数。
       首先wait_KBC_sendready。他的作用是让键盘控制电路做好准备,等待控制指令的到来。因为虽然CPU覅南路很快,但是键盘控制电路并没有那么快。如果CPU不顾设备的接受数据的能力,有些指令就会得不到执行,从而导致错误执行。如果键盘控制电路可以接受CPU指令,CPU从设备号码0x0064处所读取的数据的倒数第二位应该是0,再确认到这一个位是0之前,程序一直通过for循环来查询。break语句是从for循环中强制退出的语句。退出以后,只有return语句在那里等待执行,所以把break语句换成return语句,结果一样。
       紧接着看init_keyboard函数。它需要做到的是一边确认可否往键盘控制电路传送信息,一边发送模式设定指令,指令中包含着要设定为何种模式。模式设定的指令是0x60,利用鼠标模式的模式号码是0x47.这样鼠标控制电路就完成了。

【发送鼠标激活指令】

       这个函数与init_keyboard函数非常相似。但是不同之点在于写入的数据不同。如果往键盘控制电路发送指令0xd4,下一个数据就会自动发送给鼠标。鼠标收到激活指令后,马上就给CPU发送答复信息0xfa。

(七) 从鼠标接受数据

       取出中断指令,鼠标和键盘的原理几乎相同,不同之处在于只有送给PIC的中断受理通知。IRQ-12是从PIC的第4号,首先要通知IRQ-12受理已完成,然后再通知主PIC。这是因为主/从PIC的协调不能够自动的完成,如果程序不教给主PIC该怎么做,他就是忽视从PIC的下一个中断请求。
       我们可以发现鼠标取得数据的方法与键盘完全一样,传到设备的数据是来自键盘还是鼠标,靠中断号来区分

【取数据的程序】

       因为鼠标往往会比键盘更快的送出大量数据,所以要将FIFO缓冲区增加到128字节,这样就不会溢出了。取得数据的程序中,如果键盘和鼠标的FIFO缓冲区都为空,就执行HLT。如果不是两者都空,就先检查keyinfo,如果有数据,就取出一个显示出来。如果keyinfo是空,就再去检查mouseinfo,如果有数据,就取出一个显示出来。

二、遇到的问题及解决方法

问题1、为什么按一下键产生中断,有两个字节却只显示一个

原因:
       当按下右ctrl键时候,会产生两个字节的键码值“E0 1D”,松开之后会产生两个字节的键码值“E0 9D”。在一次产生两个字节键码值的情况下,因为键盘内部电路一次只能发送一个字节,所以一次按键就会产生两次中断,第一次中断发送E0,第二次中断发送1D。
比较:
       对于前面在a中,两次中断所发送的值都能收到,瞬间显示E0之后,接着又显示1D或9D。而在b中,HariMain函数在收到E0之前,又收到前一次按键产生的1D或9D,而这个字节就被舍弃了。

问题2、怎么让鼠标信号得到处理

       虽然作者已经介绍一点了,但是感觉只是浅显的带过了。那么想要鼠标信号得到处理,就要让下面两个装置有效,一个是鼠标控制电路,一个是鼠标本身。关于控制电路的设定:鼠标控制电路包含在键盘控制电路里,如果键盘控制电路的初始化正常完成,鼠标电路控制器的激活也就完成了。

三、程序设计创新点——姓名名字

【功能:】

       ① 在屏幕上显示自己的中文名字和学号
       ② enter按下键盘某个键(自己设置)后名字和学号的颜色开始随时间动态变化。
       ③ 按下回车之后,消失名字学号
       ④ 按下右ctrl之后,名字学号再次出现,并且颜色变换

【实现】

       ① 位置显示,设置姓名学号出现的位置。我这里名字和姓名都出现在最中间,并且名字在第一行,学号在第二行。

       ② 设置函数,因为只有键盘中断,所以我都移除了鼠标中断的部分。以下我的代码和注解

       ③ 名字设计

       ④ 延迟函数,为了让颜色变换慢一点,肉眼可以分辨出来

【现象】

       ① 初始状态

       ② 按下回车键,名字颜色变换

       ③ 按下空格键,消失

       ④ 按下右ctrl,名字再次出现

四、实验心得体会

       在这次实验中,主要需要我们提前预习,然后看会,课堂上做了节点考核,整个过程还是比较紧张刺激的,大多数同学都选择了第三题,但是我觉得我不能在短时间之类完成,所以我选择了第二种。但是我的名字说真的还挺难写的,壁画也不少,所以我将第一个字,分为两部分来写,第一个字会稍微有点大。

       总的来说还挺开心,希望明天学到更多。冲呀!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值