很多单位在开展文娱活动时有抢答一项,需要用到抢答器,普通抢答器使用通用集成电路制成,价格高、显示方式简单,性价比较差。而一般单位都有计算机,如果利用计算机就可以很方便地构成一台功能强大而价格十分低廉的抢答器。下面介绍的是笔者实际制作使用的电路。
一、打印口工作原理简介
参照图1,PC机上的打印接口共有25根连线,其中18-25都是地线,因此实际
共有17根线,分成三类,8根数据线,可进行数据输出,5根状态线,输入,4根控制线,输出。这三组线分别由打印口的三个寄存器控制,即378H(数据口),379H(状态口),37AH(控制口),只要对这三个地址的寄存器读或写,就可以输入或输出数据。而对这三个地址的读写可以用C语言中的函数outportb(int port,int data)和inportb(int port)来进行,十分方便。
二、硬件电路图
使用一片廉价的八缓冲器74LS244。
74LS244介绍:参考图2,74LS244是三态输出的八缓冲器,由2组、每组四路输入、输出构成。每组有一个控制端,由控制端的高或低电平决定该组数据被接通还是断开,功能表如下表所示。
电路介绍(参考图3):将74LS244的控制端和分别接到打印机控制端口的两个输出端,接到一个端口也可以,但要增加一个反相器,因控制端口有多余线可用,就分别接两根线,可以省些硬件。利用这两个端口分别接通两组中的一组,将两组的输出端对应并联起来,接入打印机的状态端口,这样就可以输入8路数据了。如再接入一片74LS244,可以把输入扩展到16路。打印口控制端的另一根线接入一个交流晶闸管型光耦(型号为MC3020),光耦的另一端接一个双向晶闸管和一个电灯,按图示,当该口为低电平时,指示灯亮表示可以开始抢答。
三、程序的编制
这个制作的核心程序编写是非常简单的,只要使打印口的控制端口的低两位分时为低电平,然后分别读入状态端口的数据,就可以判断是否有人抢答了。这部份的程序如下:
#define CTRL_H 0x03 /*第一组切入,此时第16脚为0,17脚为1*/
#define CTRL_L 0x0f /*第二组切入,此时第17脚为0,16脚为1*/
for(;;)
{ outportb(port_ctrl,CTRL_H); /*port_ctrl为控制端口地址,见下说明*/
inp_data_h=inportb(port_inp); /*读输入口数据*/
outportb(port_ctrl,CTRL_L); /*切入第二组*/
inp_data_l=inportb(port_inp); /*读输入口数据*/
inp_data=((inp_data_h&&0xf0)||(inp_data_l>>4); /*两次读到的数据合并*/
if(inp_data!=0x77) /*高4位输入端无任何脚接地时,应读到7,请参考图1及电路图3*/
break; /*每组仅用高4位,两组合并后0x77为两次均无任何脚接地*/
delay(10); /*延时10毫秒,实际可在此作一些界面变化的处理,增加美观*/
}
在实际制作中为充分利用PC机的资源,充分美化抢答器,采用了全图形化的编程,并加入了声音功能。即将抢答的组数在显示器上用大字显示出,并同时利用PC机上的声卡报出相应组数。具体程序由各人及计算机档次而定,笔者编的程序可在386机上流畅地运行。
四、注意事项
如果读者实际制作这个电路,还要注意以下几个问题:
1.打印口地址的确定,并非每一台计算机的打印口地址都是以上所列的地址,最常见的还有278H,279H,27AH。因此针对不同的计算机自动寻找打印口很重要,在计算机的内存中存放有打印口地址,自动查找打印口可用如下程序:
unsigned int far *fpb=(unsigned far * )0x00400008; /*在内存40:08H处单元中有打印地址*/
port_data=*fpb; /*取打印机数据口的地址*/
port_inp=*fpb+1; /*状态端口为数据口地址加1*/
port_ctrl=*fpb+2; /*控制端口为数据端口加2*/
2. 以上设计是基于标准的打印口设置,如果主板的打印口设计不标准,则以上编程会有问题。以笔者的调查,所找到的所有386、586兼容机(约10个不同品种的主板)及以上机均能正常工作,但486机主板较混乱,笔者找了5、6种486兼容机,没一台能用。但所有的品牌机都没有发现有这方面的问题,为谨慎起见,自制前最好对自已所用计算机的打印口检测一下,即将状态线分别接地,然后读出状态口数据,看是否与接线相符。在计算机用语音报出‘开始’后要先检测一次输入,如果已有人按下按钮,则属范规,如无人按下,再点亮指示灯,表示抢答可以开始。DOS下的声卡发声程序编起来比较麻烦,而且一定要计算机有声卡才行,如果打算让旧计算机发挥余热,而又想有声音功能,那不妨多花上十多元钱按图4做一个发声电路。这是一个D/A转换器,只要读出WAV文件的数据并逐一送往数据端口,就可以发声了,这部份程序如下:
void wave(char *file) /*发声函数,参数为文件名*/
{ char ch='\0';
FILE *fp;
if((fp=fopen(file,"rb"))==NULL) /*打不开文件的常规处理*/
{ printf("File%s not found!",*file);
exit(1);
}
while(!feof(fp)) /*如果未到文件尾*/
{ outportb(port_data,(int)ch); /*取出数据并送往打印口数据端口*/
delay(3); /*延时3毫秒(取决于录音时的采样速率)*/
ch=fgetc(fp);
}
fclose(fp);
}
最后给出本程序的流程图。