1 課題設計內容
此次設計提出了用AT89C51單片機為核心控制元件,設計一個簡易的搶答器,本方案以AT89C51單片機作為主控核心,與晶振、數碼管、蜂鳴器等構成六路搶答器,利用了單片機的延時電路、按鍵復位電路、時鐘電路、定時/中斷等電路,設計的六路搶答器具有實時顯示搶答選手的號碼和搶答時間的特點,還有復位電路,使其再開始新的一輪的答題和比賽,同時還利用C51語言編程,使其實現搶答器的一些基本的功能。
本設計的系統實用性強、判斷精確、操作簡單、擴展功能強。它的功能實現是比賽開始,主持人讀完題之后按下搶答鍵,聲音提示,提示音結束后搶答倒計時開始,此時數碼管開始進行10s的倒計時,直到有一個選手搶答,選手按下搶答鍵時有聲音提示并在對應的數碼管上顯示出該選手的編號和搶答所剩的時間。如果在規定的10s時間內沒有做出搶答,鳴笛提示本輪搶答結束,則此題作廢,即開始重新一輪的搶答。下一輪搶答前先將時間歸零,再按下搶答鍵即開始。搶答者回答正確后,主持人可按下加分鍵,對應于選手編號的數碼管顯示數字就增加(按下一次加一分,最高顯示9分),反之,搶答者回答錯誤后,在該選手的得分數不為0時,主持人可按下減分鍵(按下一次減一分)。如果支持人要調整搶答時間,主持人可按下加時鍵(按下一次加1s)或減時鍵(按下一次減1s)。
2 設計方案論證
根據設計內容要求,提出了如下兩種方案
方案一:以AT89C51為核心,連接LED數碼管,晶振電路,開關電路組成。其工作原理圖如下所示:
圖1 工作原理圖
圖2.1 方案一:采用RX8 驅動譯碼單片機設計的多路搶答器系統結構框圖
方案二:以AT89C51單片機作為主控核心,與晶振、數碼管、蜂鳴器等構成六路搶答器,利用了單片機的延時電路、按鍵復位電路、時鐘電路、定時/中斷等電路,設計的六路搶答器具有實時顯示搶答選手的號碼和搶答時間的特點,還有復位電路。
兩種方案的特點比較如下:方案一具有電路簡單,設計方便,耗電較少,可靠性高等特點;方案二的圖案具備的功能更多,單片機占用端口資源利用合理,。可見方案二優于其他兩種方案,因此本設計選用方案二。
3 系統硬件設計3.1方框圖
圖3.1 功能模塊圖
第一步按鍵掃描,AT89C51接收到按鍵掃描的信息確定是否開始啟動本輪搶答,當掃描鍵被按下,第二步AT89C51啟動聲音模塊,蜂鳴器發聲一段時間停止發聲,與此同時選手開始搶答,第三步AT89C51啟動LED顯示模塊,顯示搶答倒計時,和各選手的的分數,整個過程按鍵掃描一直執行,當有選手按下搶答鍵,按鍵掃描終止對選手按鍵的掃描,AT89C51啟動聲音模塊提示有選手按鍵,并將該選手的序號發送到LED顯示,第四步,按鍵掃描對加減分按鍵掃描,按鍵每按下一次對相應的選手對應的數碼管上顯示的分數加減一,直到搶答復位鍵的按下,開始新的一輪循環。當倒計時結束時選手仍然沒有按鍵,AT89C51啟動聲音模塊,提示本輪搶答結束。
3.2搶答器顯示模塊選擇
顯示模塊主要是顯示搶答的時間,組別號碼和選手得分情況。
在使用傳統的數碼管顯示。數碼管具有:低能耗、低損耗、低壓、壽命長、耐老化、防曬、防潮、防火、防高(低)溫,對外界環境要求低,易于維護,同時其精度高,稱量快,精確可靠,操作簡單。數碼顯示是采用BCD編碼顯示數字,程序編譯容易,資源占用較少。
顯示功能與硬件關系極大,當硬件固定后,如何在不引起操作者誤解的前提下提供盡可能豐富的信息,全靠軟件來解決。在這里我們使用的是七段數碼管顯示,通常在顯示上我們采用的方法一般包括兩種:一種是靜態顯示,一種是動態顯示。其中靜態顯示的特點是顯示穩定不閃爍,程序編寫簡單,但占用端口資源多;動態顯示的特點是:顯示穩定性沒靜態好,程序編寫復雜,但是相對靜態顯示而言占用端口資源少。在本設計中根據實際情況采用的是動態顯示方法。8位8段數碼管顯示電路如下圖所示。
圖 3.2 8位七段數碼管顯示電路圖
上圖中數碼管采用的是8位一體七段共陽數碼管,其中A~H段分別接到單片機的P0口,由單片機輸出的P0口數據來決定段碼值,位選碼COM1,COM2,COM3,COM4,(COM1,COM2,
COM3,COM4)分別接到單片機的P2^0,P2^1,P2^2 ,P2^3,(P2^4,P2^5,P2^6,P2^7)由單片機來決定當前該顯示的是哪一位。在圖中還有一個排阻,連接在P0口上,用作P0口的上拉電阻,保證P0口沒有數據輸出時候處于高電平狀態。
通過查表法,將其在數碼管上顯示出來,其中P0口為字型碼輸入端,P2口的8位為字選段輸入段。在這里我們通過查表將字型碼送給8段數碼管顯示的數字。
3.3 控制器
控制器主要用于對顯示、搶答、聲音、計分等模塊進行控制。
采用ATMEL公司的AT89C51作為系統控制器的CPU方案。單片機算術運算功能強,軟件編程靈活、自由度大,可以用軟件編程實現各種算法和邏輯控制,并且由于其功耗低、體積小、技術成熟和成本低等優點,使其在各個領域應用廣泛。
3.4 鍵盤電路
鍵盤是單片機不可缺少的輸入設備,是實現人機對話的紐帶。鍵盤按結構形式可以分為非編碼鍵盤和編碼鍵盤,前者用軟件方法產生鍵碼,而后者則用硬件方法來產生鍵碼。在單片機中使用的都是非編碼鍵盤,因為非編碼鍵盤結構簡單,成本低廉,非編碼鍵盤的類型很多,常用的有獨立式鍵盤,行列式鍵盤等。本設計采用獨立式鍵盤:
鍵盤接口中使用多少根I/O線,鍵盤中就有幾個按鍵,鍵盤接口使用了8根I/O口線,該鍵盤就有8個按鍵,這種類型的鍵盤,其按鍵比較少,且鍵盤中各按鍵的工作互不干擾。因此可以根據實際需要對鍵盤中的按鍵靈活的編碼。如圖2-2。
最簡單的編碼方式就是根據I/O輸入口所直接反映的相應按鍵,按下的狀態進行編碼,稱按鍵直接狀態碼,對于這樣編碼的獨立式鍵盤,CPU可以通過直接讀取I/O口的狀態來獲取按鍵的直接狀態編碼值,根據這個值直接進行按鍵識別,這樣形式的鍵盤結構簡單,按鍵識別容易。
獨立式鍵盤的缺點是需要占用比較多的I/O口線,當單片機應用系統鍵盤中需要的按鍵比較少或I/O口線比較富余時,可以采用這樣類型的鍵盤。
圖3.3獨立式鍵盤
3.5 時鐘頻率電路的設計
單片機必須在時鐘的驅動下才能工作。在單片機內部有一個時鐘振蕩電路,只需要外接一個振蕩源就能產生一定的時鐘信號送到單片機內部的各個單元,決定單片機的工作速度。時鐘電路如下圖所示。
圖3.4外部振蕩源電路
一般選用石英晶體振蕩器。此電路在加電大約延遲10ms后振蕩器起振,在XTAL2引腳產生幅度為3V左右的正弦波時鐘信號,其振蕩頻率主要由石英晶振的頻率確定。電路中兩個電容C1,C2的作用有兩個:一是幫助振蕩器起振;二是對振蕩器的頻率進行微調。
單片機在工作時,由內部振蕩器產生或由外直接輸入的送至內部控制邏輯單元的時鐘信號的周期稱為時鐘周期。其大小是時鐘信號頻率的倒數。圖中時鐘頻率為12MHz。
3.6 復位電路的設計
單片機的第9腳RST為硬件復位端,只要將該端持續4個機器周期的高電平即可實現復位,復位后單片機的各狀態都恢復到初始化狀態,其電路圖如下所示:
圖3.5 按鍵復位電路
3.7 報警電路
利用程序來控制單片機某個口線的“高”電平或“低”電平,接上蜂鳴器就能發出聲音,若再利用延時程序控制“高”或“低”電平的持續時間,就能改變蜂鳴器鳴叫的時間。
本文設計如下圖所示。圖中利用單片機的I/O端口P1^6,單片機通過設定該端口的高、低電平使蜂鳴器發聲。
圖 3.6 發聲電路
3.8 74LS245引腳及功能
圖 3.7 74LS245引腳圖
74LS245是我們常用的芯片,用來驅動led或者其他的設備,它是8路同相三態雙向總線收發器,可雙向傳輸數據。
74LS245還具有雙向三態功能,既可以輸出,也可以輸入數據。
當80C51單片機的P0口總線負載達到或超過P0最大負載能力時,必須接入74LS245等總線驅動器。
當片選端/E低電平有效時,DIR=“0”,信號由 B 向 A 傳輸;(接收)
DIR=“1”,信號由 A 向 B 傳輸;(發送)當/E為高電平時,A、B均為高阻態。
3.9系統硬件連接原理總圖
圖2-6 系統硬件連接原理圖
3.10元器件清單
8位8段數碼管
1只;
AT89S52芯片
1只;
12MHz晶振
1只;
30PF瓷片電容
2只;
10UF電解電容
1只;
電阻1KΩ、200Ω、2.2KΩ
各一只;
按鍵BUTTON
13只;
三極管PNP
1只;
蜂鳴器
1只;
排阻471、102
各一只;
74LS245
一只
4 系統軟件設計4.1程序流程圖
圖4.1 程序流程圖
4.2源程序
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
/*-----------------------------------------------------------
共陽極0-9的數碼管段碼
------------------------------------------------------------*/
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,0xc0};
/*-----------------------------------------------------------
變量定義
------------------------------------------------------------*/
sbit start=P3^6;
sbit reset=P3^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=P1^6;
sbit key8=P1^7;
sbit jia=P3^4;
sbit jian=P3^5;
sbit jia0=P3^0;
sbit jian0=P3^1;
bit action = 0;
uchar second=10,a[7]={0};
uchar timer0_count = 0;
uchar number=0;
uchar number_display = 0;
uchar k;
/*-----------------------------------------------------------
延時函數
------------------------------------------------------------*/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
/*-----------------------------------------------------------
顯示函數
------------------------------------------------------------*/
void display(uchar number,uchar second)
{
P2 = 0x01;
P0 = table[second];
delay(1);
P2 = 0x02;
P0 = table[number];
delay(1);
P2 = 0x04;
P0 = table[a[0]];
delay(1);
P2 = 0x08;
P0 = table[a[1]];
delay(1);
P2 = 0x10;
P0 = table[a[2]];
delay(1);
P2 = 0x20;
P0 = table[a[3]];
delay(1);
P2 = 0x40;
P0 = table[a[4]];
delay(1);
P2 = 0x80;
P0 = table[a[5]];
delay(1);
}
/*-----------------------------------------------------------
搶答開始按鍵檢測函數
------------------------------------------------------------*/
void start_keyscan()
{
while(start == 0)
{
key7=0;
display(number_display,second);
if(start == 1)
{
key7=1;
action = 1;
TR0 = 1;
}
}
}
/*-----------------------------------------------------------
搶答者按鍵檢測函數
------------------------------------------------------------*/
uchar key_scan8()
{
if(key1 == 0)
{
delay(8);
if(key1 == 0)
{
number = 1;
number_display = number;
}
}
if(key2 == 0)
{
delay(8);
if(key2 == 0)
{
number = 2;
number_display = number;
}
}
if(key3 == 0)
{
delay(8);
if(key3 == 0)
{
number = 3;
number_display = number;
}
}
if(key4 == 0)
{
delay(8);
if(key4 == 0)
{
number = 4;
number_display = number;
}
}
if(key5 == 0)
{
delay(8);
if(key5 == 0)
{
number = 5;
number_display = number;
}
}
if(key6 == 0)
{
delay(8);
if(key6 == 0)
{
number = 6;
number_display = number;
}
}
if(number_display != 0)
{
return number_display;
}
else
{
return 0;
}
}
/*-----------------------------------------------------------
搶答復位函數
------------------------------------------------------------*/
void reset_keyscan()
{
if(reset == 0)
{
delay(8);
if(reset == 0)
{
number_display = 0;
second=10;
}
}
}
/*-----------------------------------------------------------
主函數
------------------------------------------------------------*/
void main()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=0;
P2=0x00;
while(1)
{
reset_keyscan();
start_keyscan();
if(jia0==0)
{
delay(10);
while(jia0==0)
display(number_display,second);
second=second+1;
}
if(jian0==0)
{
delay(10);
while(jian0==0)
display(number_display,second);
second=second-1;
}
if(jia==0&&a[number-1]<9)
{
delay(10);
while(jia==0)
display(number_display,second);
a[number-1]=a[number-1]+1;
}
if(jian==0&&a[number-1]>0)
{
delay(10);
while (jian==0)
display(number_display,second);
a[number-1]=a[number-1]-1;
}
while(action)
{
while(!key_scan8()) //無人搶答
{
display(number_display,second);
if(second == 0)
{
second = 10;
break;
}
}
TR0 = 0;
key7=0;
delay(80);
display(number_display,second);
key7=1;
action = 0;
break;
}
display(number_display,second);
}
}
/*-----------------------------------------------------------
定時中斷
------------------------------------------------------------*/
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
timer0_count ++;
if(timer0_count == 20)
{
second --;
timer0_count = 0;
if(second==0)
{
key7=0;
delay(60);
key7=1;
}
}
}
|