Proteus仿真版本:proteus 7.8
程序編譯器:keil 4/keil 5
編程語言:C語言
設(shè)計編號:Q006
基本功能
1、以單片機位核心,設(shè)計一個8位搶答器:同時供8名選手比賽,分別用6個按鍵表示;
2、無人搶答時,8個跑馬燈循環(huán)點亮,數(shù)碼管顯示00;
3、設(shè)置一個系統(tǒng)清楚和搶答控制開關(guān)(開始搶答后才允許選手搶答),開關(guān)由主持人控制;
4、搶答器具有鎖存和顯示功能。選手在設(shè)定的時間內(nèi)進行搶答,搶答有效,定時器停止工作,數(shù)碼管顯示選手編號和搶答時間,并保持到主持人將系統(tǒng)清除為止;
5、搶答器具有頂是搶答功能,且一次搶答的時間由主持人設(shè)定(如20s),由加減按鍵設(shè)定;
6、當(dāng)主持人啟動“開始”鍵后,定時器進行倒計時,同時揚聲器發(fā)出短暫的聲響,聲響持續(xù)時間位0.5s左右;
7、如果定時器時間已到,無人搶答,本次搶答無效,該題作廢,系統(tǒng)報警并禁止搶答,定時器顯示器上顯示00。
概述
1.1 課程設(shè)計目的
(1) 綜合所學(xué)的單片機原理及接口技術(shù)等課程的理論知識完成本課程設(shè)計;
(2) 學(xué)習(xí)并掌握基本電路設(shè)計與使用方法,單片機的編程與應(yīng)用方法;
(3) 提高綜合分析、解決實際問題的能力。
1.2 任務(wù)和要求
本設(shè)計是以搶答為出發(fā)點??紤]到依需設(shè)定限時回答的功能,利用AT89C51單片機及外圍接口實現(xiàn)的搶答系統(tǒng),利用單片機的定時器/計數(shù)器定時和記數(shù)的原理,將軟、硬件有機地結(jié)合起來,使得系統(tǒng)能夠正確地進行計時,同時使數(shù)碼管能夠正確地顯示時間。用開關(guān)做鍵盤輸出,發(fā)光二極管和蜂鳴器發(fā)出提示。同時系統(tǒng)能夠?qū)崿F(xiàn):在搶答中,只有開始后搶答才有效,如果在開始搶答前搶答為無效;在軟件中還應(yīng)用了外部中斷,通過中斷解除搶答的鎖存,似的設(shè)計更加靈活,實用性更強。
本設(shè)計主要設(shè)計指標(biāo):
(1) 按鍵輸入模塊,包括主持人時間加,時間減,開始搶答,新一輪4個按鍵和選手一號到八號共搶8答按鍵;
(2) 顯示模塊,可以搶答實現(xiàn)倒計時和顯示搶答選手編號。
(3) 蜂鳴器模塊,用于倒計時提醒,倒計時開始后發(fā)出短暫的聲響,聲響持續(xù)的時間為0.5s左右。
1.3 系統(tǒng)結(jié)構(gòu)圖
圖1 系統(tǒng)結(jié)構(gòu)圖
主持人控制搶答器時間加減和開始,設(shè)置好時間或者使用默認時間后,按下開始按鍵即開始倒計時,每倒計時一秒蜂鳴器短暫鳴0.5提醒選手。選手在開始搶答后按下各自的按鍵搶答,一旦按下會顯示選手編號。一輪搶答結(jié)束后,主持人按下新一輪即可進入下一輪的搶答。
2理論分析與計算
倒計時主要應(yīng)用了51單片機的定時器,本設(shè)計應(yīng)用定時器產(chǎn)生50ms定時。以12Mhz的晶振來說,機器周期是1us,計滿TH0、TL0就需要216-1個數(shù),再來一個數(shù)就“溢出”產(chǎn)生中斷,一次溢出也就是65536us,約等于65.5ms,假若定時50ms需要一個預(yù)裝值(初值),總值-需要值=預(yù)裝值。預(yù)裝后,定時器從預(yù)裝值開始加值,定時器溢出中斷后,會重新從預(yù)裝值開始加值加到50ms就再產(chǎn)生中斷,從而達到了定時的目的。如果要定時1s就可以讓定時器中斷1000ms/50ms=20次。
仿真圖
源碼
4.1 主程序
主程序完成外部中斷初始化、定時器初始化、蜂鳴器模塊初始化。主程序掃描主持人不斷掃描按鍵,進行對應(yīng)的操作。
進入主程序后,顯示顯示預(yù)設(shè)的倒計時數(shù)字20,程序掃描主持人按鍵倒計時加減鍵和開始按鍵。按下開始按鍵后,倒計時開始工作,實時刷新倒計時數(shù)字,每倒計時1秒蜂鳴器beep引腳拉低0.5秒,蜂鳴器短鳴0.5秒。在掃描到選手按下按鍵后,倒計時定時器停止工作,顯示選手編號和按下?lián)尨疰I的時間。
主要(關(guān)鍵)代碼:
EA=1;
EX0=1;//外部中斷0
IT0=1;//設(shè)置下降沿觸發(fā)中斷0
TMOD=0x11;
TH0=(65536-50000)/256;//這是50ms的
TL0=(65536-50000)%256;
ET0=1;
TR0=0;
TH1=(65536-50000)/256;//這是50ms的
TL1=(65536-50000)%256;
ET1=1;
TR1=1;
time=20; //定時時間
num=0; //選手編號
flag=0; //搶答模式標(biāo)志位
beep=0;//蜂鳴器為0 不響
此段程序是完成外部中斷初始化、定時器初始化、蜂鳴器模塊初始化。完成后進入大循環(huán)。
TempData[2]=dofly_DuanMa[time/10];
//分解顯示信息,如要顯示68,則68/10=6 68%10=8
TempData[3]=dofly_DuanMa[time%10];
if(num!=0)
m=1;
if(start==0)
{
DelayMs(10);
if(start==0)
{
flag=1;
while(!start);
}
}
這段函數(shù)完成了倒計時的顯示和掃描是否開始倒計時。在沒有開始搶答時,選手按下按鍵會顯示選手編號和清零時間,一起防止選手搶答。開始搶答后,標(biāo)志位flag變?yōu)?。開始執(zhí)行按鍵掃描函數(shù)check2();
void check1()
{
if(num==1)
{
TempData[0]=dofly_DuanMa[num/10];
//分解顯示信息,如要顯示68,則68/10=6 68%10=8
TempData[1]=dofly_DuanMa[num%10];
beep=0;
Display(0,8); //數(shù)碼管顯示函數(shù)
TR0=0;
while(m);
}
假如按鍵1按下,會顯示選手編號。同時程序會卡在while(m);循環(huán)。此時除了新一輪按鍵之外的任何按鍵都系統(tǒng)沒有任何變化。
oid restart() interrupt 0//按鍵中斷處理函數(shù) 新一輪
{
m = 0;
num = 0;
TR0 = 0;
flag = 0;
time = 23;
TempData[0] = 0;
TempData[1] = 0;
TempData[2] = 0;
TempData[3] = 0;
}
新一輪按鍵是外部中斷0,即使程序一直在執(zhí)行while(m)循環(huán),按下按鍵后,程序會執(zhí)行一次中斷函數(shù),將變量清零,函數(shù)重新執(zhí)行按鍵掃描。
4.2 按鍵掃描子函數(shù)
關(guān)鍵代碼介紹
if(key1==0)
{
DelayMs(10);
if(key1==0)
{
num=1;
while(!key1);
}
}
程序一直判斷按鍵引腳電壓,按下按鍵電壓為0。按鍵會產(chǎn)生抖動,需要進行消抖處理,演示10毫秒后,如果按鍵電壓還是0,令按鍵數(shù)目num為1。表示按下的按鍵是按鍵1。供主函數(shù)處理按鍵消息。
4.3顯示子程序
關(guān)鍵代碼介紹
/*------------------------------------------------
顯示函數(shù),用于動態(tài)掃描數(shù)碼管
輸入?yún)?shù) FirstBit 表示需要顯示的第一位,如賦值2表示從第三個數(shù)碼管開始顯示
如輸入0表示從第一個顯示。
Num表示需要顯示的位數(shù),如需要顯示99兩位數(shù)值則該值輸入2
------------------------------------------------*/
void Display(unsigned char FirstBit,unsigned char Num)
{
unsigned char i;
for(i=0;i<Num;i++)
{
DataPort=0; //清空數(shù)據(jù),防止有交替重影
DUAN=1; //段鎖存
DUAN=0;
DataPort=dofly_WeiMa[i+FirstBit]; //取位碼
WEI=1; //位鎖存
WEI=0;
DataPort=TempData[i]; //取顯示數(shù)據(jù),段碼
DUAN=1; //段鎖存
DUAN=0;
DelayMs(2); // 掃描間隙延時,時間太長會閃爍,太短會造成重影
}
}
該函數(shù)用于動態(tài)掃描數(shù)碼管。輸入?yún)?shù) FirstBit 表示需要顯示的第一位,如賦值2表示從第三個數(shù)碼管開始顯示,如輸入0表示從第一個顯示。 Num表示需要顯示的位數(shù),如需要顯示99兩位數(shù)值則該值輸入2。顯示主要控制74HC573鎖存數(shù)據(jù)。先清除數(shù)據(jù),清段鎖存。然后選擇位碼。開位鎖存將數(shù)據(jù)存在位鎖存器,選擇到了需要顯示的數(shù)碼管。位鎖存完成后將數(shù)據(jù)寫進段鎖存數(shù)據(jù),將需要顯示的數(shù)據(jù)寫到數(shù)碼管中。
4.4蜂鳴器提示子函數(shù)
蜂鳴器的正極接到VCC(+5V)電源上面,蜂鳴器的負極接到三極管的發(fā)射極E,三極管的基極B經(jīng)過限流電阻R3后由單片機的beep引腳控制,當(dāng)beep輸出低電平時,三級管QS截止,沒有電流流過線圈,蜂鳴器不發(fā)聲;當(dāng)beep輸出高電平時,三級管導(dǎo)通,這樣蜂鳴器的電流形成回路,發(fā)出聲音。因此,我們可以通過程序控制beep腳的電平來使蜂鳴器發(fā)出聲音和關(guān)閉。
void timer_t0() interrupt 1
{
TH0=(65536-50000)/256;//這是50ms的
TL0=(65536-50000)%256;
t++;
beep=0;
if(t==20)//設(shè)置為20,就是1s為高1s為低
{
beep=1;
t=0;
time--;
TempData[2]=dofly_DuanMa[time/10];//分解顯示信息,如要顯示68,則68/10=6 68%10=8
TempData[3]=dofly_DuanMa[time%10];
if(time<=0)
{
time=0;
}
}
}
在50ms一次的定時器0中斷中,每10次中斷令蜂鳴器置零。第20次中斷令蜂鳴器置一。以此產(chǎn)生0.5s短暫提醒。