#includereg51.h
我們提供的服務(wù)有:成都做網(wǎng)站、網(wǎng)站制作、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、瑪納斯ssl等。為上千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的瑪納斯網(wǎng)站制作公司
#define?uchar?unsigned?char
uchar?table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f};
sbit?rstkey=P2^2;
sbit?speaker=P2^0;
void?delay(uchar?a)
{
uchar?i,j;
for(i=0;ia;i++)
for(j=0;j120;j++);
}
main()
{
uchar?i,key;
P2=0xff;
while(1)
{
i=0;
P1=table[i];
while(1)
{
key=P3;
if(key!=0)break;
}
switch(key)
{
case?0x01:i=1;break;
case?0x02:i=2;break;
case?0x04:i=3;break;
case?0x08:i=4;break;
case?0x10:i=5;break;
case?0x20:i=6;break;
case?0x40:i=7;break;
case?0x80:i=8;break;
default:break;
}
P1=table[i];//顯示按下?lián)尨鹌鞯奶?/p>
P0=key;//顯示按下鍵號的LED
while(1)
{
if(rstkey==0)break;//主持人按下復(fù)位鍵則重新開始
speaker=~speaker;//否則蜂鳴器報(bào)警
delay(250);
}
}
}
第一章?lián)尨鹌髟O(shè)計(jì)功能分析
1.1 數(shù)字搶答器的概述
對于搶答器我們大家來說都不陌生,它是用于很多競賽場合,真正實(shí)現(xiàn)先搶先答,讓最先搶到題的選手來回答問題。搶答器不僅考驗(yàn)選手的反應(yīng)速度同時(shí)也要求選手具備足夠的知識面和一定的勇氣。選手們都站在同一個(gè)起跑線上,體現(xiàn)了公平公正的原則。
1.2 設(shè)計(jì)任務(wù)與要求
基本要求:
1. 給主持人設(shè)置一個(gè)開關(guān),用來控制系統(tǒng)的清零(編號顯示數(shù)碼管滅燈)和搶答器的開始。
2. 搶答器具有數(shù)據(jù)鎖存和顯示的功能。搶答開始后,若有選手按動(dòng)搶答器按鈕,編號立即鎖存,并在LED數(shù)碼上顯示選手的編號,同時(shí)揚(yáng)聲器給出音響提示。此外,要封鎖輸入電路,禁止其他選手搶答。
發(fā)揮部分:
1. 搶答器具有定時(shí)搶答的功能,且一次搶答的時(shí)間可以由主持人設(shè)定(如30秒)。當(dāng)節(jié)目主持人啟動(dòng)“開始”鍵后,要求定時(shí)器立即減計(jì)時(shí),并用顯示器顯示,同時(shí)揚(yáng)聲器發(fā)出短暫的聲響,聲響持續(xù)時(shí)間0.5秒左右。
2. 參加選手在設(shè)定的時(shí)間內(nèi)搶答,搶答有效,定時(shí)器停止工作,顯示器上顯示選手的編號和搶答時(shí)刻的時(shí)間,并保持到主持人將系統(tǒng)清零為止。
3. 如果定時(shí)搶答的時(shí)間已到,卻沒有選手搶答時(shí),本次搶答無效,系統(tǒng)短暫報(bào)警,并封鎖輸入電路,禁止選手超時(shí)后搶答,時(shí)間顯示器上顯示00。
4. 選手如果在主持人按開始鍵之前違規(guī)搶答,系統(tǒng)報(bào)警,LED顯示違規(guī)選手號碼和FF,直到主持人按下停止鍵。
第二章 搶答器方案論證
搶答器的實(shí)現(xiàn)方式有種多樣,通過純電子器件搭建電路實(shí)現(xiàn),如優(yōu)先編碼器,鎖存器,555定時(shí)器譯碼器等,純電子器件實(shí)現(xiàn)沒有軟件參與,調(diào)試簡單,但是它不易于擴(kuò)展和修改,而且電路結(jié)構(gòu)復(fù)雜,調(diào)試?yán)щy電子,電子器件管腳很多,實(shí)際搭建起來費(fèi)時(shí)費(fèi)力,焊接很容易出錯(cuò)。于是,我想到了用單片機(jī)實(shí)現(xiàn)。單片機(jī)體積小價(jià)格低,應(yīng)用方便,穩(wěn)定可靠。單片機(jī)將很多任務(wù)交給了軟件編程去實(shí)現(xiàn),大大簡化了外圍硬件電路,使外圍電路的實(shí)現(xiàn)簡單方便。由于單片機(jī)本身不具有軟件編譯測試的功能,我們需要借助其他軟件編譯,將編譯好的程序“燒”入單片機(jī)內(nèi)。
在實(shí)際電路設(shè)計(jì)中,需要先通過仿真軟件測試電路以及編譯的程序,檢查外圍電路設(shè)計(jì)是否合理,軟件編譯是否正確,以及軟件和硬件電路能否正常配合工作,能否準(zhǔn)確的實(shí)現(xiàn)所設(shè)計(jì)的功能。如果測試通過,電路仿真沒有問題能完全實(shí)現(xiàn)功能的話就可以實(shí)際的做板子的焊接工作了。在老師的指導(dǎo)下我選擇了常用的單片機(jī)仿真軟件proteus6.9以及keil 進(jìn)行仿真。
第三章 硬件電路設(shè)計(jì)
3.1總體設(shè)計(jì)
根據(jù)搶答器的基本功能,可以設(shè)計(jì)出如下的單片機(jī)外圍電路:
圖3-1 總體設(shè)計(jì)
如圖3-1,P3.0為開始搶答,P3.2為停止,P1.0-P1.7為八路搶答輸入,數(shù)碼管段選P0口,位選P2口低3位,蜂鳴器(用綠燈代替)輸出為P3.6口。P3.2為時(shí)間加1調(diào)整,P3.3為時(shí)間減1調(diào)整。
3.2 外部振蕩電路
圖3-2 外部振蕩電路
一般選用石英晶體振蕩器。此電路在加電大約延遲10ms后振蕩器起振,在XTAL2引腳產(chǎn)生幅度為3V左右的正弦波時(shí)鐘信號,其振蕩頻率主要由石英晶振的頻率確定。電路中兩個(gè)電容 C1,C2的作用有兩個(gè):一是幫助振蕩器起振;二是對振蕩器的頻率進(jìn)行微調(diào)。C1,C2的典型值為30PF。
3.3 復(fù)位電路的設(shè)計(jì)
單片機(jī)的第9腳RST為硬件復(fù)位端,只要將該端持續(xù)4個(gè)機(jī)器周期的高電平即可實(shí)現(xiàn)復(fù)位,復(fù)位后單片機(jī)的各狀態(tài)都恢復(fù)到初始化狀態(tài),其電路圖如圖4所示:
圖3-3 復(fù)位電路
在方案中使用到了硬件復(fù)位和軟件復(fù)位兩種功能,由上面的硬件復(fù)位可使寄存器及存儲(chǔ)器的值都恢復(fù)到初始值,而前面的功能提到了倒計(jì)時(shí)間需要有記憶功能,該功能實(shí)現(xiàn)的前提條件就是不能對單片機(jī)進(jìn)行硬件復(fù)位,所以設(shè)定了軟復(fù)位功能。軟復(fù)位實(shí)際上就是當(dāng)程序執(zhí)行完畢之后,將程序指針通過一條跳轉(zhuǎn)指令讓它跳轉(zhuǎn)到程序執(zhí)行的起始地址。
3.1.4 顯示電路的設(shè)計(jì)
顯示電路使用了七段數(shù)碼管7SEG-MPX4-CC,它是共陰極的,由高電平點(diǎn)亮。
圖3-4 陰極七段數(shù)碼管
4.1.5 按鈕輸入電路的設(shè)計(jì)
搶答器的輸入按鈕使用常開開關(guān),
圖3-5 搶答按鍵
這些常開開關(guān)組成了搶答按鍵,硬件電路簡單,在程序設(shè)計(jì)上也不復(fù)雜,只要在程序中消除在按鍵過程中產(chǎn)生的“毛刺”現(xiàn)象就可以了。這里采用最常用的方法即延時(shí)法,其的原理為:因?yàn)椤懊獭泵}沖一般持續(xù)時(shí)間短,約為幾ms,而按鍵的時(shí)間一般遠(yuǎn)遠(yuǎn)大于這個(gè)時(shí)間,所以當(dāng)單片機(jī)檢測到有按鍵動(dòng)靜后再延時(shí)一段時(shí)間(這里取10ms)后再判斷此電平是否保持原狀態(tài),如果是則為有效按鍵,否則無效。
3.1.6 發(fā)聲
這里能利用程序來控制單片機(jī)P3.6口線反復(fù)輸出高電平或低電平,即在該口線上產(chǎn)生一定頻率的矩形波,接上揚(yáng)聲器就能發(fā)出一定頻率的聲音,再利用延時(shí)程序控制“高”“低”電平的持續(xù)時(shí)間,就能改變輸出頻率,從而改變音調(diào),使揚(yáng)聲器發(fā)出不同的聲音。
第四章 系統(tǒng)軟件設(shè)計(jì)
4.1 程序系統(tǒng)結(jié)構(gòu)圖
硬件電路確定后,軟件的編程要與硬件相匹配,軟硬件才能結(jié)合完成所要實(shí)現(xiàn)的功能。由功能分析得到以下的軟件結(jié)構(gòu)圖:
圖4-1 軟件系統(tǒng)結(jié)構(gòu)圖
4.2 程序流程圖
整個(gè)程序主要由定時(shí)器T0、定時(shí)器T1、外部中斷0和主程序構(gòu)成。
定時(shí)器T0用于使揚(yáng)聲器發(fā)聲,當(dāng)需要響鈴時(shí),把響鈴標(biāo)志位置一,每次中斷都對P3.7取反,揚(yáng)聲器發(fā)聲,改變定時(shí)器初值,可改變揚(yáng)聲器頻率。定時(shí)器程流程圖如下:
圖4-2 響鈴程序流程圖
定時(shí)器T1用于倒計(jì)時(shí),每次中斷為50ms,當(dāng)計(jì)數(shù)標(biāo)志為20時(shí)即為一秒,顯示數(shù)字減一。其流程圖如下:
圖4-3 倒計(jì)時(shí)中斷流程圖
外部中斷0用于調(diào)整倒計(jì)時(shí)時(shí)間,流程圖如下:
圖4-4 調(diào)整搶答時(shí)間流程圖
主程序協(xié)調(diào)三個(gè)中斷一起工作,實(shí)現(xiàn)搶答功能,其流程圖如下:
圖4-5 主程序流程圖
附錄:
程序代碼:
P3.0為開始搶答,P3.1為停止,P1.0-P1.7為八路搶答輸入,數(shù)碼管段選P0口,位選P2的低三位口,蜂鳴器輸出為P3.6口。
ORG 0000H
AJMP MAIN
ORG 0003H
AJMP INT0SUB
ORG 000BH
AJMP T0INT
ORG 001BH
AJMP T1INT
OK EQU 20H ; 搶答開始標(biāo)志位
RING EQU 22H ; 響鈴標(biāo)志位
ORG 0040H
MAIN: MOV R1,#0FH; 初設(shè)搶答時(shí)間為15s
MOV R2,#0AH; 初設(shè)答題時(shí)間為10s
MOV TMOD,#11H; 設(shè)置未定時(shí)器/模式1
MOV TH0,#0F0H
MOV TL0,#0FFH; 越高發(fā)聲頻率越高,越尖
MOV TH1,#3CH
MOV TL1,#0B0H; 50ms為一次溢出中斷
SETB EA
SETB ET0
SETB ET1
SETB EX0
SETB EX1; 允許四個(gè)中斷,T0/T1/INT0/INT1
CLR OK
CLR RING
SETB TR1
SETB TR0; 一開始就運(yùn)行定時(shí)器,以開始顯示FFF.如果想重新計(jì)數(shù),重置TH1/TL1就可以了
查詢程序:
START: MOV R5,#0BH
MOV R4,#0BH
MOV R3,#0BH
ACALL DISPLAY; 未開始搶答時(shí)候顯示FFF
JB P3.0,NEXT
ACALL DELAY
JB P3.0,NEXT;去抖動(dòng),如果"開始鍵"按下就向下執(zhí)行,否者跳到非法搶答查詢
ACALL BARK;按鍵發(fā)聲
MOV A,R1
MOV R6,A; 送R1-R6,因?yàn)镽1中保存了搶答時(shí)間
SETB OK; 搶答標(biāo)志位,用于COUNT只程序中判斷是否查詢搶答
MOV R3,#0AH; 搶答只顯示計(jì)時(shí),滅號數(shù)
AJMP COUNT;進(jìn)入倒計(jì)時(shí)程序,"查詢有效搶答的程序"在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: ACALL BARK; 按鍵發(fā)聲
MOV R3,#01H
AJMP ERROR
FALSE2: ACALL BARK
MOV R3,#02H
AJMP ERROR
FALSE3: ACALL BARK
MOV R3,#03H
AJMP ERROR
FALSE4: ACALL BARK
MOV R3,#04H
AJMP ERROR
FALSE5: ACALL BARK
MOV R3,#05H
AJMP ERROR
FALSE6: ACALL BARK
MOV R3,#06H
AJMP ERROR
FALSE7: ACALL BARK
MOV R3,#07H
AJMP ERROR
FALSE8: ACALL BARK
MOV R3,#08H
AJMP ERROR
倒計(jì)時(shí)程序(包括有效搶答程序):
COUNT: MOV R0,#00H; 重置定時(shí)器中斷次數(shù)
MOV TH1,#3CH
MOV TL1,#0B0H; 重置定時(shí)器
RECOUNT: MOV A,R6; R6保存了倒計(jì)時(shí)的時(shí)間
MOV B,#0AH
DIV AB; 除十分出個(gè)位/十位
MOV 30H,A; 十位存于(30H)
MOV 31H,B; 個(gè)位存于(31H)
MOV R5,30H ; 取十位
MOV R4,31H ; 取個(gè)位
MOV A,R6
CLR C
SUBB A,#07H
JNC LARGER ;大于5s跳到LARGER,小于等于5s會(huì)提醒
MOV A,R0
CJNE A,#0AH,FULL;1s中0.5s向下運(yùn)行
CLR RING
AJMP CHECK
FULL: CJNE A,#14H,CHECK ; 1s時(shí),響并顯示號數(shù)并清R0,重新計(jì)時(shí)
SETB RING
MOV A,R6
JZ QUIT ; 計(jì)時(shí)完畢
MOV R0,#00H
DEC R6 ; 一秒標(biāo)志減1
AJMP CHECK
LARGER: MOV A,R0
CJNE A,#14H,CHECK ; 如果1s向下運(yùn)行,否者跳到查"停/顯示"
DEC R6; 計(jì)時(shí)一秒R6自動(dòng)減1
MOV R0,#00H
CHECK: JNB P3.1,QUIT; 如按下停止鍵退出
ACALL DISPLAY
JNB P1.0,TRUE1
JNB P1.1,TRUE2
JNB P1.2,TRUE3
JNB P1.3,TRUE4
JNB P1.4,TRUE5
JNB P1.5,TRUE6
JNB P1.6,TRUE7
JNB P1.7,TRUE8
AJMP RECOUNT
QUIT: CLR OK ; 如果按下了"停止鍵"重新回到開始
CLR RING
ACALL BARK
AJMP START
正常搶答處理程序:
TRUE1: ACALL BARK; 按鍵發(fā)聲
MOV A,R2
MOV R6,A; 搶答時(shí)間R2送R6
MOV R3,#01H
CLR OK;
AJMP LOOP2
TRUE2:ACALL BARK;
MOV A,R2
MOV R6,A
MOV R3,#02H
CLR OK
AJMP LOOP2
TRUE3:ACALL BARK;
MOV A,R2
MOV R6,A
MOV R3,#03H
CLR OK
AJMP LOOP2
TRUE4:ACALL BARK;
MOV A,R2
MOV R6,A
MOV R3,#04H
CLR OK
AJMP LOOP2
TRUE5: ACALL BARK;
MOV A,R2
MOV R6,A
MOV R3,#05H
CLR OK
AJMP LOOP2
TRUE6: ACALL BARK;
MOV A,R2
MOV R6,A
MOV R3,#06H
CLR OK
AJMP LOOP2
TRUE7: ACALL BARK;
MOV A,R2
MOV R6,A
MOV R3,#07H
CLR OK
AJMP LOOP2
TRUE8: ACALL BARK;
MOV A,R2
MOV R6,A
MOV R3,#08H
CLR OK
LOOP2: AJMP DISPLAY ;搶答后停止計(jì)時(shí),等待返回
SETB RING
JNB P3.1 QUIT
AJMP LOOP2
犯規(guī)搶答程序:
ERROR: SETB RING ;犯規(guī)響鈴
MOV R5,#0BH
MOV R4,#0BH; 顯示FF和犯規(guī)號數(shù)
LOOP3: ACALL DISPLAY
JNB P3.1 QUIT1; 等待“停止”鍵按下
AJMP LOOP3
QUIT1: CLR RING
CLR OK
AJMP START
顯示程序:
DISPLAY:MOV DPTR,#DAT1; 查表顯示程序,利用P0口做段選碼口輸出/P2低三位做位選碼輸出
MOV A,R5
MOVC A,@A+DPTR
MOV P2,#01H
MOV P0,A
ACALL DELAY
MOV DPTR,#DAT2
MOV A,R4
MOVC A,@A+DPTR
MOV P2,#02H
MOV P0,A
ACALL DELAY
MOV A,R3
MOVC A,@A+DPTR
MOV P2,#04H
MOV P0,A
ACALL DELAY
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
DELAY1: MOV 35H,#08H
LOOP0: ACALL DISPLAY
DJNZ 35H,LOOP0
RET
延時(shí)(顯示和去抖動(dòng)用到):
DELAY: MOV 32H,#12H
LOOP: MOV 33H,#0AFH
LOOP1: DJNZ 33H,LOOP1
DJNZ 32H,LOOP
RET
發(fā)聲程序:
BARK: SETB RING
ACALL DELAY1
ACALL DELAY1
CLR RING; 按鍵發(fā)聲
RET
INT0(搶答時(shí)間R1調(diào)整程序):
INT0SUB:MOV A,R1
MOV B,#0AH
DIV AB
MOV R5,A
MOV R4,B
MOV R3,#0AH
ACALL DISPLAY;先在兩個(gè)時(shí)間LED上顯示R1
JNB P3.2,INC0; P3.2為+1s鍵,如按下跳到INCO
JNB P3.3,DEC0; P3.3為-1s鍵,如按下跳到DECO
JNB P3.4,BACK0; P3.4為確定鍵,如按下跳到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
TO溢出中斷(響鈴程序):
T0INT:MOV TH0,#0ECH
MOV TL0,#0FFH
JNB RING,OUT
CPL P3.6 ; RING標(biāo)志位為1時(shí)候P3.6口不短取反使喇叭發(fā)出一定頻率的聲音
OUT: RETI
T1溢出中斷(計(jì)時(shí)程序):
T1INT: MOV TH1,#3CH
MOV TL1,#0B0H
INC R0
RETI
END
先來個(gè)匯編的程序,P1接一個(gè)共陽極數(shù)碼管,P0低4位接4個(gè)搶答按鍵,主持人復(fù)位采用單片機(jī)復(fù)位按鈕實(shí)現(xiàn)。
ORG 0000H
START: MOV A,P0
ORL A,#0F0H
CJNE A,#0FFH,PL0
SJMP START
PL0: LCALL DELAY
MOV A,P0
ORL A,#0F0H
CJNE A,#0FFH,PL1
SJMP START
PL1: JNB ACC.0,K1
JNB ACC.1,K2
JNB ACC.2,K3
JNB ACC.3,K4
LJMP START
K1: MOV P1,#0F9H
SJMP $
K2: MOV P1,#0A4H
SJMP $
K3: MOV P1,#0B0H
SJMP $
K4: MOV P1,#99H
SJMP $
DELAY: MOV R6,#15
DEL2: MOV R7,#200
DJNZ R7,$
DJNZ R6,DEL2
RET
END
代碼如下:
i=2;break;
if(key==0)break;250;
sbit rstkey=P2^2;/
case 0x08:break;
case 0x04;200;j++);
default;/
#define uchar unsigned char
uchar table[]={0x3f,0x4f;break,0x06;/
P2=0xff:i=8,0x6d:i=6;
}
switch(key)
{
case 0x01,0x7f};i
case 0x80;reg51:i=7:i=1:i=3;
void delay()/,0x66;
case 0x40,0x7d:i=4;break;
}
P1=table[i];break;
case 0x10:i=5,0x07,j;
P1=table[i];break;
while(1)
{
i=0;jbreak;
case 0x02,0x5b;延時(shí)約400毫秒
{
uchar i;
for(i=0;break;
while(1)
{
key=P3,key;
case 0x20;i++)
for(j=0;/.hbreak;否則蜂鳴器報(bào)警
delay();顯示按下鍵號的LED
while(1)
{
if(rstkey==0)break;/
sbit speaker=P2^0;主持人按下復(fù)位鍵則重新開始
speaker=~speaker#include顯示按下?lián)尨鹌鞯奶?/p>
P0=key;
}
main()
{
uchar i
用鎖的機(jī)制。在產(chǎn)生線程的時(shí)候,就鎖起來。
具體的自己查下。思路是這樣的!
貌似DLAY延時(shí)時(shí)間太短,你是先顯示十位再顯示個(gè)位,每次調(diào)用XIANSH1顯示子程時(shí),十位只顯示了DLAY子程延時(shí)時(shí)間,顯示子程結(jié)束時(shí)都停留在顯示個(gè)位上,如果XIANSH1顯示子程調(diào)用不是太頻繁則基本上看不到十位的顯示效果,因?yàn)樵谝粋€(gè)調(diào)用周期內(nèi)十位只顯示了DLAY子程延時(shí)時(shí)間,其余時(shí)間都在顯示個(gè)位內(nèi)容。
如果你先顯示個(gè)位再顯示十位,恐怕又看不到個(gè)位的內(nèi)容了。
事實(shí)上對于一個(gè)逐位掃描顯示電路,在刷新每一位時(shí)盡可能使它們的時(shí)間均等,這樣顯示效果才會(huì)均勻。