reactos操作系统实现(24)
在很早的电脑里,就带有一个小喇叭,可以发出不同频率的声音。主要用来判断系统是否有问题使用,比如BIOS检查硬有问题时,就会发出不同的声音,提醒用户是那里出问题了。在操作系统里,也经常使用这个小喇叭来提醒用户是什么问题,比如输入非法的按键时,就响一声。在早期的五笔输入法时,输入的字不对,就会用这个小喇叭提醒,让忘打的操作人员回到屏幕上选择所需要的字。那么这个小喇叭的驱动是怎么样进行的呢?这里就来研究这个问题,在ReactOS的HAL层代码如下: #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微机中 采用与8255和8253芯片功能兼容的类8255和类8253芯片)。 8255芯片通过I/O端口61H的PB1和PBO两位来选择扬声器的驱动。当PBO为1时,控制825 33定时器发出脉冲;当PB1为1时,扬声器的与门电路接通并一直保持到PB1变到)时关闭;在此 期间,由8253芯片通道2以及选通扬声器的作用。 8253芯片有三个相同且各自独立的通道,其通道2的输出OUT2在初始化后发出一定频率 的脉冲信号。此脉冲信号可以通过对通道的编程而进行改变,这样,就使得扬声器能发出各 种频率的声音。我们用程序设定通道2输出波形的频率和延续时间,就能控制扬声器的单调 和发声的长短。 2.发声软件设计及实例 根据发声电路,我们知道要使扬声器发出一定频率的声音,需要完成以下几项工作: ①根据已知的声音频率,求送8253芯片通道2的计数时间常数TIME; ②往8253指令寄存器(43H)送指令码oB6H,使通道2输出脉冲信号; ③把时间常数TIME送入8253的通道2; ④把8255芯片的PB1、PBO置为1,开启扬声器; ⑤持续若干时间。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |