一、設計背景
? ? ? ? 近年來隨著科技的飛速發展,單片機的應用正在不斷的走向深入。本文闡述了基于51單片機的八路搶答器設計。本設計中,51單片機充當了核心控制器的角色,通過IO口與各個功能模塊相連接。按鍵模塊負責檢測參與者的搶答動作,當有人按下搶答按鈕時,會通過IO口電平的變化通知單片機,單片機會記錄按鍵的次序,并通過數碼管顯示當前的搶答結果。
? ? ? ? 為了保證搶答過程的準確性和公平性,設計中還需要考慮到以下因素。首先,按鍵模塊需要具備快速響應和高可靠性,以確保搶答者的動作能夠被準確地捕捉到。其次,顯示屏模塊需要能夠實時更新搶答結果,并顯示相應的信息,比如參與者的編號和搶答時間。最后,在電路連接方面,需要注意各個模塊之間的線路布局,以避免信號干擾和電氣問題。
? ? ? ?軟件系統采用C語言編寫程序,包括顯示程序,定時中斷服務,延時程序等,并在KEIL5中調試運行,硬件系統利用PROTEUS8.11強大的功能來實現,簡單切易于觀察,在仿真中就可以觀察到實際的工作狀態。
二、實現功能
? ? ? ? 以51單片機為控制核心,設計一種四路搶答器。整個系統包括MCU、晶振電路、時鐘電路、功能按鍵以及數碼管顯示。該系統利用共陽數碼管實時顯示搶答倒計時時間,通過獨立按鍵設計控制搶答器的啟動、復位、以及不同選手的搶答。可具體實現以下功能:
? ? ? ? (1) 按下啟動鍵后,在10s倒計時的過程中,按下任意路搶答按鍵,數碼管上對應顯示搶答選手的序號并開始60s倒計時,60s倒計時結束后,搶答數據清零。
? ? ? ? (2) 按下復位鍵后,搶答器復位,再次按下啟動鍵可以實現新一輪的搶答。
? ? ? ? (3)·定時器定時50ms,20次定時可產生1秒鐘計時。
三、仿真演示
未運行仿真時,數碼管不顯示。
運行仿真后,進入準備界面,數碼管顯示默認搶答序號0和搶答倒計時10秒。
按下啟動按鍵,進入搶答界面,開始10秒搶答倒計時,并在數碼管上實時顯示。
在搶答倒計時范圍內,按下序號為1~4的選手搶答按鍵,搶答倒計時歸零,數碼管上顯示搶答選手序號和倒計時60秒。
60s倒計時結束后,數碼管顯示0-00,表示1次搶答結束。
按下復位按鈕恢復到準備界面,以便進行下一次搶答。
四、源程序(部分)
#include "reg52.h"
#include "delay.h"
#include "smg.h"
#include "timer.h"sbit key1 = P1^0; //四位選手
sbit key2 = P1^1;
sbit key3 = P1^2;
sbit key4 = P1^3;sbit start_stop = P3^6; //搶答按鈕_bool action = 0;
_bool key1_flag = 0;
_bool key2_flag = 0;
_bool key3_flag = 0;
_bool key4_flag = 0;_bool reset_flag = 0; //復位標志位
_bool start_stop_flag = 0; //搶答標志位uint8 second = 10; //時間
uint8 timer0_count = 0; //定時器1計數值
uint8 number = 0; //隊號
uint8 number_display = 0; //隊號顯示uint8 key_scan8(void);
void start_stop_keyscan(void);
/*-----------------------------------------------------------
主函數
------------------------------------------------------------*/
void main()
{ConfigTimer0();//定時器初始化while(1){start_stop_keyscan();//開始按鍵while(action)//按下開始鍵為1,搶答結束為0{while(!key_scan8()&&!reset_flag) //無隊搶答{display(number_display,second);if(second == 0){break;}}if(number_display)//有隊搶答{second=60;}while(number_display&&!reset_flag){display(number_display,second);TR0 = 1;if(second == 0){break;}}TR0 = 0;//時間到display(number_display,second);action = 0;//搶答結束break;}display(number_display,second); }
}/*-----------------------------------------------------------
中斷服務函數
------------------------------------------------------------*/
void timer0() interrupt 1
{TH0 = (65536-50000)/256; //50msTL0 = (65536-50000)%256; timer0_count ++;if(timer0_count == 20)//1s{timer0_count = 0;second--; //10s倒計時if(second == 0)//計時結束{TR0 = 0;number_display = 0;action = 0;}}
}/*-----------------------------------------------------------
開始鍵掃描函數
------------------------------------------------------------*/
void start_stop_keyscan(void)
{if(start_stop == 0){Delay_ms(8);if((start_stop == 0)&&(!start_stop_flag)){start_stop_flag = 1;action = 1;TR0 = 1;reset_flag = 0;}}else{start_stop_flag = 0; }
}/*-----------------------------------------------------------
四位搶答鍵掃描函數
------------------------------------------------------------*/
uint8 key_scan8(void)
{if(key1 == 0){Delay_ms(8);if((key1 == 0)&&(!key1_flag)){key1_flag = 1;number = 1;number_display = number;}}else{key1_flag = 0;number = 0; }if(key2 == 0){Delay_ms(8);if((key2 == 0)&&(!key2_flag)){key2_flag = 1;number = 2;number_display = number;}}else{key2_flag = 0;number = 0; }if(key3 == 0){Delay_ms(8);if((key3 == 0)&&(!key3_flag)){key3_flag = 1;number = 3;number_display = number;}}else{key3_flag = 0;number = 0; }if(key4 == 0){Delay_ms(8);if((key4 == 0)&&(!key4_flag)){key4_flag = 1;number = 4;number_display = number;}}else{key4_flag = 0;number = 0; }if(number_display != 0) {return 1;}else{return 0;}
}/*-----------------------------------------------------------
復位鍵外部中斷函數
------------------------------------------------------------*/
void EXINT0() interrupt 0 //外部中斷0觸發函數
{if(!reset_flag){reset_flag = 1;number_display = 0;action=0;second=10;}}
仿真源文件及源程序百度網盤鏈接:https://pan.baidu.com/s/1xKDNPqCrTqCiqI-F8pCGcQ?
提取碼:v8a3?