reactos操作系统实现(24)

 在很早的电脑里,就带有一个小喇叭,可以发出不同频率的声音。主要用来判断系统是否有问题使用,比如BIOS检查硬有问题时,就会发出不同的声音,提醒用户是那里出问题了。在操作系统里,也经常使用这个小喇叭来提醒用户是什么问题,比如输入非法的按键时,就响一声。在早期的五笔输入法时,输入的字不对,就会用这个小喇叭提醒,让忘打的操作人员回到屏幕上选择所需要的字。那么这个小喇叭的驱动是怎么样进行的呢?这里就来研究这个问题,在ReactOSHAL层代码如下:

#001  /*

#002   * @implemented

#003   */

#004  BOOLEAN

#005  NTAPI

#006  HalMakeBeep(IN ULONG Frequency)

#007  {

#008      UCHAR Data;

#009      ULONG Divider;

#010      BOOLEAN Result = TRUE;

#011 

#012      /* FIXME: Acquire CMOS Lock */

#013 

 

关闭寄存器。

#014      /* Turn the register off */

#015      Data = READ_PORT_UCHAR(PORT_B);

#016      WRITE_PORT_UCHAR(PORT_B, Data & 0xFC);

#017 

 

检查是否有输出的频率。

#018      /* Check if we have a frequency */

#019      if (Frequency)

#020      {

 

根据时钟和频率来计算产生波形的定时器值。

#021          /* Set the divider */

#022          Divider = CLOCKFREQ / Frequency;

#023 

 

溢出判断。

#024          /* Check if it's too large */

#025          if (Divider > 0x10000)

#026          {

#027              /* Fail */

#028              Result = FALSE;

#029              goto Cleanup;

#030          }

#031 

 

设置定时器的值,就可以产生相应的波形来发出声音。

#032          /* Set timer divider */

#033          WRITE_PORT_UCHAR(TIMER3, 0xB6);

#034          WRITE_PORT_UCHAR(TIMER2, (UCHAR)(Divider & 0xFF));

#035          WRITE_PORT_UCHAR(TIMER2, (UCHAR)((Divider>>8) & 0xFF));

#036 

#037          /* Turn speaker on */

#038          WRITE_PORT_UCHAR(PORT_B, READ_PORT_UCHAR(PORT_B) | 0x03);

#039      }

#040 

#041  Cleanup:

#042      /* FIXME: Release hardware lock */

#043 

#044      /* Return result */

#045      return Result;

#046  }

 

发声原理:

扬声器接受两个发声信号:一个来自定时器芯片(8253)的通道2的输出

信号OUT2;另一个来自外围设备接口芯片(8255)端口B的第一位发出的信号(:386微机中

采用与82558253芯片功能兼容的类8255和类8253芯片)

8255芯片通过I/O端口61HPB1PBO两位来选择扬声器的驱动。当PBO1,控制825

33定时器发出脉冲;PB11,扬声器的与门电路接通并一直保持到PB1变到)时关闭;在此

期间,8253芯片通道2以及选通扬声器的作用。

8253芯片有三个相同且各自独立的通道,其通道2的输出OUT2在初始化后发出一定频率

的脉冲信号。此脉冲信号可以通过对通道的编程而进行改变,这样,就使得扬声器能发出各

种频率的声音。我们用程序设定通道2输出波形的频率和延续时间,就能控制扬声器的单调

和发声的长短。

2.发声软件设计及实例

根据发声电路,我们知道要使扬声器发出一定频率的声音,需要完成以下几项工作:

①根据已知的声音频率,求送8253芯片通道2的计数时间常数TIME;

②往8253指令寄存器(43H)送指令码oB6H,使通道2输出脉冲信号;

③把时间常数TIME送入8253的通道2;

④把8255芯片的PB1PBO置为1,开启扬声器;

⑤持续若干时间。

你可能感兴趣的:(编程,timer,工作,输入法)