利用单片机做抢答器,有很多种方案了,下面的链接,就是一个很简单的:
http://zhidao.baidu.com/question/503668881.html
按照这个方案,做而论道设计了如下电路图:
图片链接:http://xiangce.baidu.com/picture/detail/9a74432216c6d02f5af47f5cca156ecf751ccfea
这是刚开始(或者主持人按下了清零键)时的画面。
主持人此时正在叙述题目,还没有按下开始键。如果这时有选手违规,提前按键,本控制器就会鸣音报警,《违规》指示灯也会发光。
主持人按清零键后,再按下开始键,《抢答中》指示灯就会发光,数码显示器显示 30 秒倒计时,在这以后,选手才可以按下抢答键。
下面就是 5 号选手抢答成功的画面。
图片链接:http://xiangce.baidu.com/picture/detail/767ac4c1d02f0a83802564f76ecf741c697bc0ce
本电路使用的程序如下:
;==========================================
KAI BIT P3.5 ;开始
FUW BIT P3.6 ;清零(复位)
GAI BIT P3.7 ;修改时间
;----------------------
SPK BIT P2.5 ;扬声器
GRE BIT P2.6 ;绿灯(用于抢答期间)
YEL BIT P2.7 ;黄灯(用于违规警告)
;------------------------------------------
ORG 0000H
JMP START
ORG 0003H
JMP X0_INT
ORG 000BH
JMP T0_INT
START:
MOV TMOD, #01H
MOV IE, #82H
MOV SP, #60H
SETB IT0 ;下降沿触发中断
;----------------------;下面是清零(复位)
FUWEI:
MOV TH0, #4CH ;50ms@11.0592MHz
MOV TL0, #0
MOV R2, #20 ;预置中断次数
MOV R3, #0 ;显示秒数0
MOV R4, #0 ;选手号码
MOV 20H, #0 ;各个标志清零
MOV P2, #255 ;关闭所有显示
CLR IE0
SETB EX0 ;开中断,谁提前抢答,将出错
;----------------------;下面等待按下"开始"键
KAISHI:
CALL DISP
JB 20H.1, WG ;有选手提前按键, 违规
JB KAI, KAISHI ;没有按"开始",就循环
;----------------------;按下了
MOV R3, #30 ;秒数30
SETB TR0 ;开始倒计时
CLR GRE
WAIT: ;等待抢答
CALL DISP
JB 20H.1, XS ;有选手按键则转
JB 20H.2, CHAOSHI ;超时了则转
JMP WAIT ;继续等待
;----------------------
XS: ;查找选手按键的位置
JNB 21H.0, J0
JNB 21H.1, J1
JNB 21H.2, J2
JNB 21H.3, J3
JNB 21H.4, J4
JNB 21H.5, J5
JNB 21H.6, J6
; JMP J7
J7: INC R4
J6: INC R4
J5: INC R4
J4: INC R4
J3: INC R4
J2: INC R4
J1: INC R4
J0: INC R4
CLR TR0
SETB GRE
SETB 20H.3
MOV R5, #0
CALL DISP
DJNZ R5, $ - 2
;----------------------;下面等待按下复位键
W_FW:
CLR 20H.3
CALL DISP
JB FUW, W_FW ;没有按,则转
JMP FUWEI
;----------------------
CHAOSHI: ;超时处理
CLR TR0
SETB 20H.3 ;允许发音
MOV R5, #100
CALL DISP ;边显示边发音
DJNZ R5, $ - 2
JMP W_FW ;去等待按下复位
;----------------------
WG: ;违规按键处理
CLR YEL
SETB 20H.3
MOV R5, #200
CALL DISP
DJNZ R5, $ - 2
JMP W_FW ;去等待按下复位
;==========================================
;外部中断0, 选手按键将触发本中断
;==========================================
X0_INT: ;有选手按键了
MOV 21H, P1 ;立即读入
CLR EX0 ;关闭中断,再也不响应后来的按键
SETB 20H.1 ;设置标志
RETI
;==========================================
;T0定时中断, 每隔50ms中断一次
;==========================================
T0_INT: ;到了预定时间
MOV TH0, #4CH; ;重装50ms初始值
DJNZ R2, T0_EXIT ;未满20次,跳出
MOV R2, #20
DEC R3 ;秒数减一
CJNE R3, #255, T0_EXIT ;不到-1则转
INC R3
SETB 20H.2 ;超时标志
T0_EXIT:
RETI
;==========================================
;显示子程序, 逐个显示一遍
;==========================================
DISP: ;显示一遍约有10ms
PUSH ACC
PUSH B
;------------------------
MOV A, R4 ;取来选手号码
CALL OUT_DM ;输出段码
CLR P2.3 ;显示
CALL DELAY
SETB P2.3
;------------------------
MOV A, #10
CALL OUT_DM ;输出段码
CLR P2.2 ;显示'-'
CALL DELAY
SETB P2.2
;------------------------
MOV A, R3 ;取来秒数
MOV B, #10
DIV AB
CALL OUT_DM ;输出段码
CLR P2.1 ;显示十位
CALL DELAY
SETB P2.1
;------------------------
MOV A, B
CALL OUT_DM ;输出段码
CLR P2.0 ;显示个位
CALL DELAY
SETB P2.0
;------------------------
POP B
POP ACC
RET
;------------------------
OUT_DM:
ADD A, #(D_TAB - $ - 3)
MOVC A, @A + PC
MOV P0, A
RET
;------------------------
D_TAB:
DB 0C0H,0F9H,0A4H,0B0H, 99H ;共阳极0-9
DB 92H, 82H,0F8H, 80H, 90H,0BFH ;-
;------------------------------------------
DELAY: ;延时约2500us
JB 20H.3, BEEP
MOV R6, #5
MOV R7, #50
DJNZ R7, $
DJNZ R6, $ - 2
RET
;------------------------------------------
BEEP:
MOV R6, #2 ;
CLR SPK
DJNZ R7, $
SETB SPK
DJNZ R7, $
DJNZ R6, BEEP + 2
RET
;==========================================
END
程序有些长,故此,删除了设置倒计时时间的程序段。
本程序对各个选手的按键处理,使用了中断方式,这在一定的程度上,提高了对按键先、后的甄别能力。
当有任意一个抢答键被按下,在 2us 之内,就会被单片机保存起来。
后按键的选手,只要晚了 2us,就不会进入单片机。
如果有两个或多个选手,都是在 2us 之内按键,本程序将认定其中编号最小的选手,是最先按下的。
呵呵,还是有些不公平啊 !
提高单片机的晶振频率,可以提高对按键先后的甄别能力。
如果对甄别要求很高,就应该使用纯电子器件构成的抢答判别电路。
这样的电路,可以参考做而论道前面发表的博文。