基於51微控制器的搶答器設計

題目:搶答器設計

1

系統設計

1。1

設計要求

1。1。1

設計任務

基於微控制器的搶答器的設計,實現搶答器的基本功能。

1。1。2

效能指標要求

1。 需要自己設計電路並焊接電路板。

2。有一個主持人控制開關和6路搶答按扭,當主持人允許搶答時才能進行搶答操作,並用一個數碼管顯示搶答選手的號碼,同時其他選手不能再搶答。

3。當主持人允許搶答後倒計時5秒時間,在這5秒內搶答有效,過後就不能進行搶答了。

4。電路上要加個蜂鳴器的電路,當有選手搶答時蜂鳴器響一下。

5.當有選手搶答後,進行倒計時20秒作為選手回答問題時間,用兩個數碼管顯示,倒計時時間到時有聲光提示。

6.畫電路板時要增加下載介面,方便除錯程式。

7.擴充套件功能(選做)

用按鍵可設定倒計時的時間,範圍在5秒到30秒之間。

1。2

設計思路及設計框圖

1。2。1

設計思路

本次實訓是基於微控制器STC89C52晶片來擴充套件的搶答器。

首先先設定支援人開始搶答按鍵,在晶片的P1^6腳處接入按鍵,按鍵按下,蜂鳴器響來實現這個搶答開始訊號。在主持人開始允許搶答時,六位選手連線的微控制器從P1^0—P1^5口的任意一位選手進行搶答,搶答時間為5s,搶答後設定回答問題時間為5s—30s,倒計時5s時LED燈亮,並且蜂鳴器響。所搶答的選手號碼、搶答時間與回答時間均將位元組送入數碼管中顯示。用兩個按鍵來掌控回答問題的時間,時間加計數與時間減計數。當需要重新進行搶答時則按下與晶片的RST段(即9腳)連線的按鍵則可以實現。所搶答的選手號碼、搶答時間與回答時間均將位元組送入數碼管中顯示。P0口接的是一個四位一體共陰數碼管,P2。4、P2。2、P2。1、P2。0作為數碼管的位選。由於微控制器自身IO口的驅動能力不能讓蜂鳴器發出聲音,因此要透過三極體NPN來放大電流,這樣才能使蜂鳴器發出聲音。

1。2。2

總體設計款圖

基於51微控制器的搶答器設計

2

各個模組設計

2。1

微控制器

STC89C52模組

基於51微控制器的搶答器設計

P0-P3:佔32個引腳,其中P0是低8位地址線/資料線埠,P1是資料線埠,P2是高8位地址線/資料線埠,P3是資料線/第二功能線埠。

EA~ /VPP:片外程式ROM有效程式設計電源,作EA~用時為輸出訊號,EA~=0片外程式ROM有效,EA~=1片內ROM有效,作VPP用時為電源輸入。

XTAL1和XTAL2:外部時鐘震盪輸入端

VCC:+5V電源。

VSS:地

RST/VPD:復位/備用電源接入。正常工作時作復位訊號引入,當VCC失電時,此腳接入備用電源,使片內RAM中的資料處於底功能保護。

2。2選手按鍵電路

基於51微控制器的搶答器設計

該電路是由6個按鍵開關組成,實現6位選手搶答的終端,每一個開關連線一個I/O(P1。0-P1。5),注意按鍵的公共端接地,當微控制器的腳懸空時為高電平,按下時為低電平。

2。3時鐘頻率振盪電路

基於51微控制器的搶答器設計

微控制器必須在時鐘的驅動下才能工作。在微控制器內部有一個時鐘振盪電路,只需要外接一個振盪源就能產生一定的時鐘訊號送到微控制器內部的各個單元,決定微控制器的工作速度。此電路在加電大約延遲10ms後振盪器起振,在XTAL2引腳產生幅度為5V左右的正弦波時鐘訊號,其振盪頻率主要由石英晶振的頻率確定。電路中兩個電容C2、C3的作用有兩個:一是幫助振盪器起振;二是對振盪器的頻率進行微調。C2、C3的典型值為22pF。

2。4復位電路

基於51微控制器的搶答器設計

給微控制器一個復位訊號使程式重頭開始執行,一般有兩種復位方式:上電覆位和手動復位。在此作品中的復位採用手動復位方式,復位電路是微控制器初始化,使微控制器重新開始執行程式,當復位鍵按下,RST由低電平變為高電平,則程式從頭開始執行。

2。5數碼管顯示電路

基於51微控制器的搶答器設計

該電路是為了更好地顯示出各時段的情況也是讓我們能直觀的看到各個狀態,該電路由8位排阻和4位數碼管組成,8為排阻的每一管腳接著數碼管的段碼a、b、c、d、e、f、g、dp有助於提高數碼管的亮度,s1、s2、s3、s4是數碼管的位選,連線著微控制器的I/O(P2。0、P2。1、P2。2、P2。3)數碼管由微控制器程式控制位選和段選,按我們的要求顯示。

2。6電源電路

基於51微控制器的搶答器設計

該電源電路是為了更好的顯示電路中電源導通狀態。

2。7蜂鳴器控制電路

基於51微控制器的搶答器設計

蜂鳴器VCC端接著VCC,GND端連線著NPN三極體的集電極,當三極體的基極送來高電平時NPN三極體導通即蜂鳴器導通,發出聲音,三極體基極獲得的高電平由程式控制,程式判斷搶答開關按下後就給三極體基極送出高電平,三級管基極需要接上拉電阻一個,才能得到足夠的電壓開啟三極體。

2。8下載口模組

為了實現我們編好的程式可以正常下載到微控制器,就需要在電路中新增微控制器下載口,電路的設計,下載口的2、3端分別連線微控制器的RXD、TXD,4管腳接GND,1管腳接+5V。

3 除錯過程

3。1焊接過程

本次實訓用的是洞洞板焊接,與以往的打板子不同,洞洞板沒有明確的元器件擺放位置和相應的焊點,所以需要自己規劃好每個元件的擺放位置以及每條線路的連線方式,是使用跳線還是直接透過一條焊錫拉過去,並且焊接的過程需要很仔細很小心,少接一條線,都有可能會導致整個電路都不連通,由於是第一次使用洞洞板,所以我的線路佈局有些雜亂,使用了很多跳線讓板子看起來很雜亂,而且花費了較多的時間才完成本次實訓的焊接過程。

3。2除錯過程

焊接好電路後,通上電蜂鳴器不響並且數碼管也不會亮,並且程式也不能下載進微控制器,在檢查後發現少連線了一條線導致微控制器與數碼管都沒有通上電源,並且由於焊接的時候沒有正確的瞭解到按鍵同一側是相連的導致按鍵也沒有作用,在都完善了以後,蜂鳴器卻怎麼都不會響,但用微控制器相應管腳直接連上vcc蜂鳴器卻會一直響,證明了電路連線沒有問題,最後在查閱了資料後,發現可以把蜂鳴器放在三極體的發射極,在更改了電路後蜂鳴器能正常執行。

4 功能測試

4。1 測試儀器與裝置

萬用表,下載線

4。2 效能指標測試

1、接通電源,電源燈亮,搶答指示燈亮,數碼管亮。

2、按下主持人按鍵,數碼管上顯示5秒倒計時,5秒計時結束後LED亮、蜂鳴器響。

3、在5秒搶答時間內按下選手按鍵,數碼管上顯示選手號碼,同時顯示20秒倒計時。

倒計時結束後,LED亮、蜂鳴器響。

4、復位鍵,數碼管歸零。

5、設定鍵可調節搶答時間與回答時間,加到三十秒自動回到五秒鐘。

實物圖:

基於51微控制器的搶答器設計

5、電路原理圖

基於51微控制器的搶答器設計

程式:

#include

sbit BEEP = P2^0;

sbit LED1 = P2^3;

sbit LED2 = P2^2;

sbit LED3 = P2^1;

#define duanPore P0 //數碼管段控制埠,高電平有效

sbit DIG1 = P2^4;

sbit DIG2 = P2^5;

sbit DIG3 = P2^6;

sbit DIG4 = P2^7;

sbit KEY1 = P1^0;

sbit KEY2 = P1^1;

sbit KEY3 = P1^2;

sbit KEY4 = P1^3;

sbit KEY5 = P1^4;

sbit KEY6 = P1^5;

sbit KEY7 = P3^2;

sbit KEY8 = P3^3;

unsigned char code tab_duan[19] =

{

0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,

0x77,0x7c,0x39,0x5e,0x79,0x71,

0x40,0x00,0x48

};

unsigned char dat_buf[4] = {17, 17, 0, 5};

int time = 5, time1 = 5, time2 = 20;

unsigned char i = 0;

unsigned int count = 0;

bit flag_lock = 1;

void DelayMs(unsigned int ms); //延時函式

void dig_scan(unsigned char *dat); //數碼管顯示掃描

unsigned char KeyScan(void); //獨立按鍵掃描

void InitTimer0(void); //定時器0初始化

void alarm(void); //報警函式

void AnswerTask(void); //搶答任務

void SetTime(void); //設定倒計時時間

void main(void)

BEEP = 0;

LED1 = 1;

InitTimer0();

time = time1;

while(1)

{

if(KeyScan() == 7)

{

alarm();

AnswerTask();

}

if(KeyScan() == 8)

SetTime();

dat_buf[0] = 17;

dat_buf[1] = 17;

dat_buf[2] = time / 10;

dat_buf[3] = time % 10;

dig_scan(dat_buf);

}

}

void DelayMs(unsigned int ms) //延時函式

unsigned char a,b,c;

while(——ms)

for(c=1;c>0;c——)

for(b=142;b>0;b——)

for(a=2;a>0;a——);

void dig_scan(unsigned char *dat) //數碼管顯示掃描

switch(i)

case 0:

duanPore = tab_duan[dat[0]];

DIG1 = 0;

break;

case 1:

duanPore = tab_duan[dat[1]];

DIG2 = 0;

case 2:

duanPore = tab_duan[dat[2]];

DIG3 = 0;

case 3:

duanPore = tab_duan[dat[3]];

DIG4 = 0;

default: break;

DelayMs(5);

DIG1 = 1;

DIG2 = 1;

DIG3 = 1;

DIG4 = 1;

++i;

if(i > 3)

i = 0;

unsigned char KeyScan(void) //獨立按鍵掃描

if(KEY1 == 0)

{

LED2 = 0;

LED3 = 1;

DelayMs(10);

if(KEY1 == 0)

return 1;

if(KEY2 == 0)

if(KEY2 == 0)

return 2;

if(KEY3 == 0)

DelayMs(10);

if(KEY3 == 0)

return 3;

if(KEY4 == 0)

{

if(KEY4 == 0)

return 4;

if(KEY5 == 0)

if(KEY5 == 0)

return 5;

if(KEY6 == 0)

if(KEY6 == 0)

return 6;

if(KEY7 == 0)

LED3 = 0;

if(KEY7 == 0)

return 7;

if(KEY8 == 0)

if(KEY8 == 0)

return 8;

return 0;

void Timer0Interrupt(void) interrupt 1 //定時器

TH0 = (65536 - 10000) / 256;

TL0 = (65536 - 10000) % 256;

++count;

if(count > 100)

count = 0;

——time;

if(time <= 0)

TR0 = 0;

BEEP = 1;

LED1 = 0;

LED2 = 1;

LED3 = 1;

flag_lock = 0;

}

void InitTimer0(void)

TMOD = 0x01;

TH0 = (65536 - 10000) / 256;

EA = 1;

ET0 = 1;

TR0 = 0;

void alarm(void) //報警

BEEP = 1;

DelayMs(300);

BEEP = 0;

void AnswerTask(void) //搶答

unsigned char key_val;

TR0 = 1;

if(flag_lock == 1)

{

key_val = KeyScan();

switch(key_val)

{

case 1:

{

dat_buf[0] = key_val;

dat_buf[1] = 16;

time = time2;

alarm();

flag_lock = 0;

break;

}

case 2:

flag_lock = 0;

case 3:

time = time2;

case 4:

case 5:

case 6:

dat_buf[0] = key_val;

default: break;

}

dat_buf[2] = time / 10;

dat_buf[3] = time % 10;

dig_scan(dat_buf);

void SetTime(void) //調時

{

unsigned char mode = 0;

if(KeyScan() == 8)

alarm();

++mode;

if(mode >= 2)

break;

if(KeyScan() == 7)

if(mode == 0)

++time1;

if(time1 > 30)

time1 = 1;

if(mode == 1)

++time2;

if(time2 > 99)

time2 = 1;

if(mode == 0)

dat_buf[0] = 16;

dat_buf[1] = time1 / 10;

dat_buf[2] = time1 % 10;

dat_buf[3] = 16;

if(mode == 1)

dat_buf[0] = 18;

dat_buf[1] = time2 / 10;

dat_buf[2] = time2 % 10;

dat_buf[3] = 18;

dig_scan(dat_buf);

time = time1;