抢答器。内含源文件,仿真,课程设计word,程序软件为keil,欢迎分享
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载):
单片机汇编语言源程序如下:
- 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
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
抢答器.zip
(43.83 KB, 下载次数: 136)
单片机课程设计2.rar
(719.13 KB, 下载次数: 144)
|