怎样用单片机做八路抢答器
答案:3 悬赏:70
解决时间 2021-02-28 15:58
- 提问者网友:生亦何欢
- 2021-02-28 12:46
怎样用单片机做八路抢答器
最佳答案
- 二级知识专家网友:疯山鬼
- 2021-02-28 14:03
拿一个口,接8个按键,给这8个按键编号。让单片机实时扫描这些按键,检测到有按下的,就终止扫描,处理相应的键值。那个建按下就让数码管显示相应的编号就是了,很简单的。
全部回答
- 1楼网友:爱情是怎么炼成的
- 2021-02-28 17:13
ok equ 20h;抢答开始标志位
ring equ 22h;响铃标志位
org 0000h
ajmp main
org 0003h
ajmp int0sub
org 000bh
ajmp t0int
org 0013h
ajmp int1sub
org 001bh
ajmp t1int
org 0040h
main: mov r1,#30;初设抢答时间为30s
mov r2,#60;初设答题时间为60s
mov tmod,#11h;设置未定时器/模式1
mov th0,#0f0h
mov tl0,#0ffh;越高发声频率越高,越尖
mov th1,#3ch
mov tl1,#0b0h;50ms为一次溢出中断
setb ea
setb et0
setb et1
setb ex0
setb ex1;允许四个中断,t0/t1/int0/int1
clr ok
clr ring
setb tr1
setb tr0;一开始就运行定时器,以开始显示fff.如果想重新计数,重置th1/tl1就可以了
;=====查询程序=====
start: mov r5,#0bh
mov r4,#0bh
mov r3,#0bh
acall display;未开始抢答时候显示fff
jb p3.0,next;ddddddd
acall delay
jb p3.0,next;去抖动,如果"开始键"按下就向下执行,否者跳到非法抢答查询
acall bark;按键发声
mov a,r1
mov r6,a;送r1->r6,因为r1中保存了抢答时间
setb ok;抢答标志位,用于count只程序中判断是否查询抢答
mov r7,#01h ;读抢答键数据信号标志,这里表示只读一次有用信号
mov r3,#0ah;抢答只显示计时,灭号数
ajmp count;进入倒计时程序,"查询有效抢答的程序"在count里面
next: jnb p1.0,false1
jnb p1.1,false2
jnb p1.2,false3
jnb p1.3,false4
jnb p1.4,false5
jnb p1.5,false6
jnb p1.6,false7
jnb p1.7,false8
ajmp start
;=====非法抢答处理程序=====
false1: mov r3,#01h
ajmp error
false2: mov r3,#02h
ajmp error
false3: mov r3,#03h
ajmp error
false4: mov r3,#04h
ajmp error
false5: mov r3,#05h
ajmp error
false6: mov r3,#06h
ajmp error
false7: mov r3,#07h
ajmp error
false8: mov r3,#08h
ajmp error
;=====int0(抢答时间r1调整程序)=====
int0sub:mov a,r1
mov b,#0ah
div ab
mov r5,a
mov r4,b
mov r3,#0ah
acall display;先在两个时间led上显示r1
jnb p3.4,inc0;p3.4为+1s键,如按下跳到inco
jnb p3.5,dec0;p3.5为-1s键,如按下跳到deco
jnb p3.1,back0;p3.1为确定键,如按下跳到backo
ajmp int0sub
inc0: mov a,r1
cjne a,#63h,add0;如果不是99,r2加1,如果加到99,r1就置0,重新加起。
mov r1,#00h
acall delay1
ajmp int0sub
add0: inc r1
acall delay1
ajmp int0sub
dec0: mov a,r1
jz setr1;如果r1为0, r1就置99,
dec r1
acall delay1
ajmp int0sub
setr1: mov r1,#63h
acall delay1
ajmp int0sub
back0: reti
;=====int1(回答时间r2调整程序)=====
int1sub:mov a,r2
mov b,#0ah
div ab
mov r5,a
mov r4,b
mov r3,#0ah
acall display
jnb p3.4,inc1
jnb p3.5,dec1
jnb p3.1,back1
ajmp int1sub
inc1: mov a,r2
cjne a,#63h,add1
mov r2,#00h
acall delay1
ajmp int1sub
add1: inc r2
acall delay1
ajmp int1sub
dec1: mov a,r2
jz setr2
dec r2
acall delay1
ajmp int1sub
setr2: mov r2,#63h
acall delay1
ajmp int1sub
back1: reti
;=====倒计时程序(抢答倒计时和回答倒计时都跳到改程序)=====
repeat:mov a,r2 ;使用锦囊时重新计时
mov r6,a
clr ring
count: mov r0,#00h;重置定时器中断次数
mov th1,#3ch
mov tl1,#0b0h;重置定时器
recount:mov a,r6;r6保存了倒计时的时间,之前先将抢答时间或回答时间给r6
mov b,#0ah
div ab;除十分出个位/十位
mov 30h,a;十位存于(30h)
mov 31h,b;个位存于(31h)
mov r5,30h;取十位
mov r4,31h;取个位
mov a,r6
subb a,#07h
jnc larger;大于5s跳到larger,小于等于5s会提醒
mov a,r0
cjne a,#0ah,full;1s中0.5s向下运行
clr ring
ajmp check
full: cjne a,#14h,check;下面是1s的情况,响并显示号数并清r0,重新计
setb ring
mov a,r6
jz quit;计时完毕
mov r0,#00h
dec r6;一秒标志减1
ajmp check
larger: mov a,r0
cjne a,#14h,check;如果1s向下运行,否者跳到查"停/显示"
dec r6;计时一秒r6自动减1
mov r0,#00h
check: jnb p3.1,quit;如按下停止键退出
jnb ok,checkk ;只在回答倒计时才有效
ajmp nextt
checkk:jnb p3.0,repeat ;判断是否使用锦囊
nextt: acall display
jb ok,accout;如果是抢答倒计时,如是则查询抢答,否者跳过查询继续倒数(这里起到锁抢答作用)
ajmp recount
accout:
mov a,36h
jnb acc.0,true1
jnb acc.1,true2
jnb acc.2,true3
jnb acc.3,true4
jnb acc.4,true5
jnb acc.5,true6
jnb acc.6,tz1
jnb acc.7,tz2
ajmp recount
tz1:jmp true7
tz2:jmp true8
quit: clr ok;如果按下了"停止键"执行的程序
clr ring
ajmp start
;=====正常抢答处理程序=====
true1: acall bark
mov a,r2
mov r6,a;抢答时间r2送r6
mov r3,#01h
clr ok;因为答题的计时不再查询抢答,所以就锁了抢答
ajmp count
true2:acall bark
mov a,r2
mov r6,a
mov r3,#02h
clr ok
ajmp count
true3:acall bark
mov a,r2
mov r6,a
mov r3,#03h
clr ok
ajmp count
true4:acall bark
mov a,r2
mov r6,a
mov r3,#04h
clr ok
ajmp count
true5:acall bark
mov a,r2
mov r6,a
mov r3,#05h
clr ok
ajmp count
true6: acall bark
mov a,r2
mov r6,a
mov r3,#06h
clr ok
ajmp count
true7:acall bark
mov a,r2
mov r6,a
mov r3,#07h
clr ok
ajmp count
true8:acall bark
mov a,r2
mov r6,a
mov r3,#08h
clr ok
ajmp count
;=====犯规抢答程序=====
error: mov r0,#00h
mov th1,#3ch
mov tl1,#0b0h
mov 34h,r3;犯规号数暂存与(34h)
here: mov a,r0
cjne a,#06h,flash;0.3s向下运行->灭并停响
clr ring
mov r3,#0ah
mov r4,#0ah
mov r5,#0ah;三灯全灭
ajmp check1
flash: cjne a,#0ch,check1;下面是0.8s的情况,响并显示号数并清r0,重新计
setb ring
mov r0,#00h
mov r3,34h;取回号数
mov r5,#0bh
mov r4,#0bh;显示ff和号数
ajmp check1
check1: jnb p3.1,quit1
acall display
ajmp here
quit1: clr ring
clr ok
ajmp start
;=====显示程序=====
display:mov dptr,#dat1;查表显示程序,利用p0口做段选码口输出/p2低三位做位选码输出,
mov a,r3
movc a,@a+dptr
mov p2,#0feh
mov p0,a
acall delay2
mov dptr,#dat2
mov a,r5
movc a,@a+dptr
mov p2,#0fdh
mov p0,a
acall delay2
mov a,r4
movc a,@a+dptr
mov p2,#0fbh
mov p0,a
acall delay2
ret
dat1:db 00h,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,00h,71h
;"灭","1","2","3","4","5","6","7","8","9","灭","f"
dat2:db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,00h,71h
;第一个为零,其他与上相同,因为十位如果为零显示熄灭
;====加减时间延时(起到不会按下就加n个数)======
delay1: mov 35h,#08h
loop0: acall display
djnz 35h,loop0
ret
;=====延时4236个机器周期(去抖动用到)=====
delay: mov 32h,#12h
loop: mov 33h,#0afh
loop1: djnz 33h,loop1
djnz 32h,loop
ret
;=====延时4236个机器周期(显示用到)=====
delay2: mov 32h,#43h
loop3: mov 33h,#1eh
mov a,r7 ;每隔60~70个机器周期读一次p1口,全为1时为无效数据,继续读,有一个不为1时,转到正常抢答处理
jnz aaaa1 ;没读到有效数据时继续转到aaaa1
loop2: djnz 33h,loop2
djnz 32h,loop3
ret
;=====读抢答按键数据口程序=====
;由于在读抢答数据口的时候,单片机首先进入倒计时程序,再调用显示程序,最后才检测按键口
;然而在检测按键口时动态扫描要调用三次(4ms)延时程序.这样就会导致读数据口出现滞后,造成1号优先最高.8号最低.
;故采用在延时子程序中加了读数据口程序.保证了灵敏度和可靠性
aaaa1: mov a,p1
cjne a,#0ffh,aa1 ;当不全为1时的数据为有效数据
aa0: mov 36h,a ;将有效数据送到36h暂存
ajmp loop2
aa1: dec r7
ajmp aa0
;=====发声程序=====
bark: setb ring
acall delay1
acall delay1
clr ring;按键发声
ret
;=====to溢出中断(响铃程序)=====
t0int: mov th0,#0ech
mov tl0,#0ffh
jnb ring,out;
cpl p3.6;ring标志位为1时候p3.6口不短取反使喇叭发出一定频率的声音
out: reti
;=====t1溢出中断(计时程序)=====
t1int: mov th1,#3ch
mov tl1,#0b0h
inc r0
reti
end
- 2楼网友:冷眼_看世界
- 2021-02-28 15:38
用单片机做抢答器,判断先后的精确度不足。
我要举报
如以上问答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯
• 手机登qq时,显示手机磁盘不足,清理后重新登 |
• 刺客的套装怎么选啊? |