① 30秒倒計時器課程設計
【摘 要】籃球比賽30秒鍾規則規定:進攻球隊在場上控球時必須在30秒鍾內投籃出手(NBA比賽為24秒,全美大學體育聯合會比賽中為35秒),因此在比賽時裁判既要看比賽又要看秒錶計時,而本文介紹的30秒倒計時器可以解決此問題。
【關鍵詞】AT89C51單片機、30秒倒計時器、LED
30秒倒計時器的設計和製作有很多方法,本文介紹的30秒倒計時器以AT89C51單片機作為控制單元,採用兩個數碼管顯示時間,用三個按鍵分別控制計時器的計時開始、復位和暫停。倒計時器初始狀態顯示「30」,當裁判員按下計時鍵,30秒倒計時開始,當計時器時間減到0時,計時器發出聲光報警,提示裁判計時時間已到。
一、電路設計
30秒倒計時器的電路主要由電源電路、單片機最小系統、按鍵輸入、顯示驅動電路、報警電路組成,30秒倒計時器控制電路如圖1所示。
圖1 30秒倒計時器電路原理圖
1、按鍵輸入
「30秒倒計時器」採用了三個按鍵來完成計數器的啟動計數、復位、暫停/繼續計數等功能。
(1)K1鍵:啟動按鈕(P3.2)。
按下K1鍵,計數器倒計時開始,數碼管顯示數字從30開始每秒遞減計數,當遞減到到零時,報警電路發出聲、光報警信號。當計數器處於暫停狀態時按下K1鍵將回到計時狀態。
(2)K2鍵:復位按鈕(P3.3)。
按下K2鍵,不管計數器工作於什麼狀態,計數器立即復位到預置值 「30」 ,在報警狀態時按下K2鍵還可取消報警。
(3)K3鍵:暫停/計時切換按鈕(P3.4)。
當計數器處於計時狀態時按下該鍵計數器暫停計時,數碼管顯示數字保持不變;當計數器處於暫停狀態按下該鍵計數器將回到計時狀態;初始狀態時該鍵無效。
2、顯示驅動電路
「30秒倒計時器」用兩個共陽數碼管來顯示時間,數碼管顯示方式為動態顯示。顯示驅動電路中,數碼管的段碼引腳通過470歐的電阻接到單片機的P1口,兩個片選引腳各通過一個9012連接到正5V電源,由P3.0和P3.1控制。
4、報警電路
計時時間減到0,顯示數碼管顯示「00」時,發光二極體D1由P3.5控制發出光報警,同時蜂鳴器由P3.7控制發出聲報警。
二、軟體編程思路
1、全局變數
「30秒倒計時器」動作流程主要受三個全局變數控制。首先是bit變數「act」,當「act」為「1」時倒計時開始,為「0」時倒計時停止,「act」初值為「0」,可以由按鈕操作將其置「1」或清「0」。第二個全局變數是char變數「time」,存放倒計時的時間,當倒計時時間為0時,發出聲光報警。變數「time」的初值為30,定時中斷服務程序在「act」為1時,每1s對其進行減1操作,減到0時保持為0,按下「復位鍵」可將「time」復位為30。第三個全局變數是int變數「t」,記錄響應定時中斷0的次數。根據初始化定義,定時器0以方式1工作,每1ms發出一次中斷請求。控製程序只開放了定時器0中斷,因此不會有比定時器0中斷更高級的中斷被允許,所以每次請求都會立刻被響應。響應後在中斷服務程序中將全局變數「t」加1記錄響應中斷次數,每響應1000次即為1秒鍾。變數「t」初值為0,在中斷服務程序中加1,當「t」為2000時由中斷服務程序清0。在按鍵驅動程序中,按下啟動鍵、復位鍵、暫停/啟動鍵時將「t」清0,目的是從0ms開始計時。
2、控制流程
主程序主要用來檢測全局變數「time」當「time」為0時發出「聲光報警」。按鍵驅動、顯示驅動和「time」操作都在定時器0中斷服務程序中進行。其控制流程如圖2所示。
圖2 控制流程圖
三、軟體程序設計
1、數碼管驅動程序
到計時器的兩個數碼管以動態顯示的方式顯示計時時間「time」(全局變數),LED1顯示「time」的十位,LED2顯示「time」的個位。
(1)定義段碼數據口和片選信號
根據實際電路,在C51中定義段碼的數據口為P1,兩個片選信號為P3.0和P3.1。定義如下:
#define an P1
sbit wei1=P3^0;
sbit wei2=P3^1;
(2)定義字形碼
LED顯示數字0~9以及全滅的字形碼表格放在數組zixing[]中。字形碼是固定的表格,定義時加上關鍵字「code」 表示該表格存放在程序存儲器中。
unsigned char code zixing[]=
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff
};
(3)定義數碼管LED1和LED2的顯示變數
為了增加驅動程序的可移植性,筆者為數碼管LED1和LED2定義了顯示變數。顯示變數就是本驅動程序的對外介面,外部程序只要改變顯示變數的值就可改變數碼管顯示的數值。定義方式如下:
unsigned char led_str[2]={10,10};
led_str[0]直接對應數碼管LED1, led_str[1]直接對應數碼管LED2。本項目中由專門的子程序將全局變數time計算拆分成led_str[0]和led_str[1]。
void js()
{
led_str[1]=time/10%10;
led_str[0]=time%10;
}
(4)數碼管驅動程序
數碼管驅動程序「void chushi(char i)」在定時中斷服務程序中被調用執行。根據初始化程序的定義,定時中斷服務程序每1ms被執行一次。定時中斷服務程序中運用全局變數「t」記錄進入該服務程序的次數,「t」計滿2000由定時中斷服務程序清零。
數碼管驅動程序的參數「char i」是用來確定當前點亮的是LED1還是LED2,當參數為「0」時點亮LED1,參數為「1」時點亮LED2。如果我們希望偶數次進入定時中斷服務程序時點亮LED1,奇數次進入定時中斷服務程序時點亮LED2,我們可以用程序調用語句「chushi(t%2);」輕松實現。
進入數碼管驅動程序後首先調用子函數js(),計算當前的led_str[0]和led_str[1]。接下來將兩個數碼管全部熄滅以防止余暉的出現。最後點亮需要點亮的數碼管並送出字型碼。驅動程序代碼如下:
void chushi(char i)
{
js(); //計算顯示變數
an=0xff; //去余暉
wei1=i; wei2=!i; //確定片選
an=zixing[led_str[i]]; //送字型碼
}
2、按鍵驅動程序
按鍵驅動程序分為按鍵識別和按鍵功能執行兩部分。按鍵功能執行可在按鍵按下時或按鍵抬起後執行,文中將其設計在按鍵抬起後執行。
(1)定義按鍵I/O地址
根據實際電路,三個按鍵(啟動鍵、復位鍵、暫停/啟動鍵)分別接在P3口的P3.2,P3.3和P3.4三個引腳上。為了取鍵值方便還將P3口定義為「iokey」,程序中可作定義如下:
#define iokey P3
sbit key1=P3^2;
sbit key2=P3^3;
sbit key3=P3^4;
(2)按鍵驅動流程
按鍵識別的通用流程為:I/O口寫「1」→判斷有無鍵按下→延時去抖→確定鍵值→等待按鍵抬起→執行按鍵功能。按鍵驅動程序中定義了兩個靜態變數「ts」 和「kv」,分別用來延時去抖和存放鍵值。
(3)延時去抖
靜態變數「ts」用來延時去抖。按鍵驅動程序在定時中斷服務程序中每1ms被執行一遍,每檢測到有鍵按下「ts」加1,檢測到無鍵按下「ts」清0。按鍵連續按下20ms,則連續20次執行按鍵驅動程序時都檢測到有鍵按下,此時靜態變數「ts」累加到20,可確認按鍵按下有效。
為防止按鍵一直按著不放而使「ts」累加到溢出,確認有鍵按下後可使「ts」的值保持為20,或大於20的某一個值如21。
(4)取鍵值
確認有鍵按下後即可通過讀取按鍵的I/O口狀態來得到鍵值。為讀取P3.2、P3.3和P3.4引腳狀態,屏蔽P3口其他引腳的影響,可將讀取後的數值按位或上11100011B(0xE3)再送給靜態變數「kv」。
靜態變數「kv」存放按鍵的鍵值,無鍵按下或按鍵抬起後kv的值為0。按下啟動鍵key1時kv=11111011B(0xFB),按下復位鍵key2時kv=11110111B(0xF7),按下暫停/啟動鍵key3時kv=11101111B(0xEF)。
(5)執行按鍵功能
按鍵抬起後第一次執行按鍵驅動程序時,靜態變數「kv」任保持著按鍵按下時最後得到的鍵值,以該鍵值作為參數調用按鍵執行程序「actkey(kv);」即可執行按鍵功能。調用後kv值立刻清0,確保按一次鍵執行一次按鍵功能。驅動程序代碼如下:
void key()
{
static unsigned char kv=0;
static unsigned char ts=0;
key1=1;key2=1;key3=1;
if(!(key1&key2&key3))
{
ts++;
if(ts>=20)ts=20; //有鍵按下
if(ts==20)
kv=iokey|0xe3; //取鍵值
}
else
{ //無鍵按下或按鍵已抬起
actkey(kv);
ts=0;
kv=0;
}
}
函數actkey(kv)用來根據鍵值「kv」執行相應操作。當「kv」等於0xFB時代表啟動鍵key1按下,函數actkey(kv)將全局變數act賦值為「1」。當「kv」等於0xF7時代表復位鍵key2按下,函數actkey(kv)將全局變數「time」復位為「30」。當「kv」等於0xEF時代表暫停/啟動鍵按下,函數actkey(kv)將全局變數act取反。每按一個按鈕都有將全局變數「t」清0的操作,目的是每當復位、或啟動計時時,進入定時中斷的次數都從0開始計算,否則會出現第1秒計時不準確的現象。程序代碼如下:
void actkey(unsigned char k)
{
switch(k)
{
case 0xfb:act=1;t=0;break;
case 0xf7:time=30;t=0; break;
case 0xef:act=~act;t=0; break;
}
}
四、結束語
本文在編程過程中以面向對象的編程思路封裝了兩個LED數碼管和三個獨立按鍵。當其驅動程序在定時中斷服務程序中被調用,編程者只要操作其介面:數組「led_str[2]」和函數「actkey(unsigned char k)」,無需直接對硬體進行編程即可改變功能,增強了軟體的通用性和可移植性。
② 具有倒計數顯示功能的定時開關電路設計
用數字電路實現搶答器
一、設計目標
設計一個帶有用戶選手按下後,其他用戶選手按下無效,同時,響警報、顯示是誰按下的。由主持人開關復位的搶答器。
二、 基本功能
我設計的搶答器有如下功能:有人按下時,顯示是誰按下的。同時,其他人再按下時電路不做任何處理。也就是說,如果有人按下以後,別人再按的話電路既不會顯示是他按下的。
三、搶答器的組成
搶答器的一般構成框圖如圖2-1所示。它主要由開關陣列電路、觸發鎖存電路、編碼器、7段顯示器幾部分組成。下面逐一給予介紹。
(1)開關陣列電路
該電路由多路開關所組成,每一競賽者與一組開關相對應。開關應為常開型,當按下開關時,開關閉合;當松開開關時,開關自動彈出斷開。
(2)觸發鎖存電路
當某一開關首先按下時,觸發鎖存電路被觸發,在輸出端產生相應的開關電平信息,同時為防止其它開關隨後觸發而產生紊亂,最先產生的輸出電平變化又反過來將觸發電路鎖定。若有多個開關同時按下時,則在它們之間存在著隨機競爭的問題,結果可能是它們中的任一個產生有效輸出。
(3)編碼器
編碼器的作用是將某一開關信息轉化為相應的8421BCD碼,以提供數字顯示電路所需要的編碼輸入。
圖3-1 搶答器的組成框圖
(4)7段顯示解碼器
解碼驅動電路將編碼器輸出的8421BCD碼轉換為數碼管需要的邏輯狀態,並且為保證數碼管正常工作提供足夠的工作電流。
(5)數碼顯示器
數碼管通常有發光二極體(LED)數碼管和液晶(LCD)數碼管。本設計提供的為LED數碼管。
四、搶答器的工作原理
(1)開關陣列電路
圖1.2所示為8路開關陣列電路,從圖上可以看出其結構非常簡單。電路中,R1~R8為上拉和限流電阻。當任一開關按下時,相應的輸出為低電平,否則為高電平。
圖4-1 開關陣列電路
(2)觸發鎖存電路
圖3-1所示為8路觸發鎖存電路。
圖中,74HC373為8D鎖存器,一開始,當所有開關均未按下時,鎖存器輸出全為高電平,經8輸入與非門和非門後的反饋信號仍為高電平,該信號作為鎖存器使能端控制信號,使鎖存器處於等待接收觸發輸入狀態;當任一開關按下時,輸出信號中必有一路為低電平,則反饋信號變為低電平,鎖存器剛剛接收到的開關被鎖存,這時其它開關信息的輸入將被封鎖。由此可見,觸發鎖存電路具有時序電路的特徵,是實現搶答器功能的關鍵。
(3)編碼器
如圖4-3所示,74HC147H為10-4線優先(高位優先)編碼器,當任意輸入為低電平時,輸出為相應的輸入編號的8421碼(BCD碼)的反碼。
圖4-2 8路觸發鎖存電路。
圖4-3 10-4線優先編碼器
(4)解碼驅動及顯示單元
編碼器實現了對開關信號的編碼並以BCD碼的形式輸出。為了將編碼顯示出來,需用顯示解碼電路將計數器的輸出數碼轉換為數碼顯示器件所需要的輸出邏輯和一定的電流。一般這種解碼通常稱為7段解碼顯示驅動器。常用的7段解碼顯示驅動器有CD4511等。
數碼顯示器件中的液晶數碼管價格較高,驅動較復雜,並且僅能工作於有外界光線的場合,所以使用較少。大多情況下使用的是LED數碼管。平時使用較多的LED數碼有單字和雙字之分。
LED數碼管尺寸有大有小,一般小的數碼管每個數字筆畫為一個發光二極體,而尺寸較大的數碼管一個筆畫可能是多個發光二極體串接而成的,這時一般無法直接用解碼驅動器直接驅動(其輸出高電平一般為3V左右)。
(5)解鎖電路
當觸發鎖存電路被觸發鎖存後,若要進行下一輪的重新搶答,則需將鎖存器解鎖。可將使能端強迫置1或置0(根據具體情況而定),使鎖存順處於等待歉收狀態即可。
五、改進、簡化設計
(1)功能簡介
搶答器同時供8名選手或8個代表隊比賽,分別用8個按鈕S0 ~ S7表示。設置一個系統清除和搶答控制開關S,該開關由主持人控制。
搶答器具有鎖存與顯示功能。即選手按動按鈕,鎖存相應的編號,並在LED數碼管上顯示,同時揚聲器發出報警聲響提示。選手搶答實行優先鎖存,優先搶答選手的編號一直保持到主持人將系統清除為止。
搶答器具有定時搶答功能,且一次搶答的時間由主持人設定(如30秒)。當主持人啟動"開始"鍵後,定時器進行減計時,同時揚聲器發出短暫的聲響,聲響持續的時間0.5秒左右。
參賽選手在設定的時間內進行搶答,搶答有效,定時器停止工作,顯示器上顯示選手的編號和搶答的時間,並保持到主持人將系統清除為止。
如果定時時間已到,無人搶答,本次搶答無效,系統報警並禁止搶答,定時顯示器上顯示00。
(2)設計原理圖
如圖2-1所示為總體方框圖。其工作原理為:接通電源後,主持人將開關撥到"清除"狀態,搶答器處於禁止狀態,編號顯示器滅燈,定時器顯示設定時間;主持人將開關置開始"狀態,宣布"開始"搶答器工作。定時器倒計時,揚聲器給出聲響提示。
選手在定時時間內搶答時,搶答器完成:優先判斷、編號鎖存、編號顯示、揚聲器提示。當一輪搶答之後,定時器停止、禁止二次搶答、定時器顯示剩餘時間。如果再次搶答必須由主持人再次操作"清除"和"開始"狀態開關。
圖5-1 總體設計
(3)電路設計
(1)
(2)
圖5-2 完整電路
搶答器電路參考電路如圖5-2所示。
該電路完成兩個功能:一是分辨出選手按鍵的先後,並鎖存優先搶答者的編號,同時解碼顯示電路顯示編號;二是禁止其他選手按鍵操作無效。工作過程:開關S置於"清除"端時,RS觸發器的
端均為0,4個觸發器輸出置0,使74LS148的 =0,使之處於工作狀態。當開關S置於"開始"時,搶答器處於等待工作狀態,當有選手將鍵按下時(如按下S5),74LS148的輸出 經RS鎖存後,1Q=1, =1,74LS48處於工作狀態,4Q3Q2Q=101,經解碼顯示為"5"。
此外,1Q=1,使74LS148 =1,處於禁止狀態,封鎖其他按鍵的輸入。當按鍵松開即按下時,74LS148的 此時由於仍為1Q=1,使 =1,所以74LS148仍處於禁止狀態,確保不會出二次按鍵時輸入信號,保證了搶答者的優先性。
如有再次搶答需由主持人將S開關重新置;清除"然後再進行下一輪搶答。74LS148為8線-3線優先編碼器,表5-1為其功能表。
表5-1功能表
由節目主持人根據搶答題的難易程度,設定一次搶答的時間,通過預置時間電路對計數器進行預置,計數器的時鍾脈沖由秒脈沖電路提供。
可預置時間的電路選用十進制同步加減計數器74LS192進行設計,具體電路如圖4-4所示。(3)報警電路由555定時器和三極體構成的報警電路如圖5-4所示。
其中555構成多諧振盪器,振盪頻率fo=1.43/〔(RI+2R2)C〕,其輸出信號經三極體推動揚聲器。PR為控制信號,當PR為高電平時,多諧振盪器工作,反之,電路停振。
本電路給出了所有相關電路,對於發聲報警電路只有左下角555電路。時序控制電路是搶答器設計的關鍵,它要完成以下三項功能:
1、主持人將控制開關撥到"開始"位置時,揚聲器發聲,搶答電路和定時電路進人正常搶答工作狀態。
2、當參賽選手按動搶答鍵時,揚聲器發聲,搶答電路和定時電路停止工作。
3、當設定的搶答時間到,無人搶答時,揚聲器發聲,同時搶答電路和定時電路停止工作。工作原理:當555電路的到信號後,開始產生高低電壓不同的方波,這些方波從555電路的輸出端出來,經過510歐姆的保護電阻進入放大電路。信號經過放大後,再傳給揚聲器,這時信號已經不再是方波,而是一種連續變化的一種類似於簡諧波的電信號。但是他的頻率還是和555電路的輸出端的頻率一樣。
圖5-4 定時電路
圖5-5揚聲器設計
根據上面的功能要求,設計的時序控制電路如4-5圖所示。
圖中,門G1的作用是控制時鍾信號CP的放行與禁止,門G2的作用是控制74LS148的輸人使能端 。圖11、4的工作原理是:主持人控制開關從"清除"位置撥到"開始"位置時,來自於圖5-5中的74LS279的輸出 1Q=0,經G3反相, A=1,則時鍾信號CP能夠加到74LS192的CPD時鍾輸入端,定時電路進行遞減計時。
同時,在定時時間未到時,則"定時到信號"為 1,門G2的輸出 =0,使 74LS148處於正常工作狀態,從而實現功能①的要求。當選手在定時時間內按動搶答鍵時,1Q=1,經 G3反相, A=0,封鎖 CP信號,定時器處於保持工作狀態;同時,門G2的輸出 =1,74LS148處於禁止工作狀態,從而實現功能②的要求。當定時時間到時,則"定時到信號"為0, =1,74LS148處於禁止工作狀態,禁止選手進行搶答。
同時, 門G1處於關門狀態,封鎖 CP信號,使定時電路保持00狀態不變,從而實現功能③的要求。集成單穩觸發器74LS121用於控制報警電路及發聲的時間。
(4)需要器材:
1.數字實驗箱。
2. 集成電路74LS148 1片,74LS279 1片,74LS48 3片,74LS192 2片,NE555 2片,74LS00 1片,74LS121 1片。
3. 電阻 510Ω 2隻,1KΩ 9隻,4.7kΩ l只,5.1kΩ l只,100kΩ l只,10kΩ 1隻, 15kΩ 1隻, 68kΩ l只。
4.電容 0.1uF 1隻,10uf 2隻,100uf 1隻。
5. 三極體 3DG12 1隻。
6. 其它:發光二極體2隻,共陰極顯示器3隻。
六、其他設計思路
電路設計的思路方法多樣可以滿足不同需求。 而且我還考慮了很多不同的設計思路,這些不同的思路,他們所用到的器件也不同。下面的內容是我參考的其他的大致的設計方法
使用JK觸發器實現用戶選手的信號輸入和電路的鎖存,使一個用戶選手輸入信號後其他選手輸入信號不再有效。在使用戶選手輸入信號的鎖存電路組的輸出信號,也就是JK觸發器組的輸出信號作為二-十進制解碼器的輸入信號產生十進制8421信號。
這個過程可以採用一些與非門電路完成也可以採用7442二-十進制解碼器或者74148優先編碼器他們都可以達到輸入單信號,輸出8421十進制信號的目的完成信號轉換的作用。為完成下一個步驟做准備。
在完成上兩個步驟以後,就可以將得到的8421十進制信號傳送給顯示解碼器用來顯示數字,這給數字應該是用戶選手的序列號,來表示是誰按下的。這樣,就可以實現一個新功能了。
同時,可以從很多地方取輸出信號,傳送給555電路用來產生一定頻率的方波信號。這種頻率應該是人類耳朵能夠分辨的頻率,超過或低於這個頻率范圍,普通人就聽不見了,那麼這種電路的設計就失去了意義。
從這個555電路傳出來的方波信號,在通過保護電阻後,送到放大電路,將信號放大。這時,到達放大電路輸出端的信號已經變成一種簡諧波,不再是方波。在將輸出端信號中的直流成分通過電容器予以去掉,就可以將信號送到蜂鳴器了。這時蜂鳴器也能發出聲音了。就又實現了一個功能。
從任意一個能用的輸出端例如從555電路的輸入端取信號送到一個發光二極體,就可以實現如果有人按下以後,就發光的功能。也可以在送到一個放大電路上,接上一個功率較大的發光器件上,使得發光效果更明顯。
另外,二-十進制轉換器也可以用一些與非門來完成。如圖6-1
圖6-1 2-10進制轉換電路
七、學年設計總結
實習給了我們一個很好的提高動手能力的機會。平常我們只是在頭腦中去抽象的記憶、理解那些課本上的理論知識。有的理論知識很好懂,但是有的理論知識確是晦澀難懂的,甚至只是靠自己的死記硬背去記住。但是我們都知道,那樣的記憶只是一時的,很快你就會忘記。而這次的實習卻給了我們一個在實踐中靈活運用知識的機會,我們通過在實踐中發現問題,進而去書本中找相關的知識去解決問題,從而鞏固了理論知識。那樣的知識是你從根本上去認識它,理解它,所以你的記憶時間會很長。
③ 利用單片機設計實現一個60秒倒計時顯示裝置,並且計時到後發出報警聲音。
#include<reg52.h>
sbitbz=P3^1;
unsignedchara[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90};
unsignedcharn,time=60;
main()
{
P1=a[0];
P2=a[6];
TMOD=0X01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET0=1;
TR0=1;
while(1);
}
timer0()interrupt1
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
if(time!=0)
{
n++;
if(n==100)
{
n=0;
time--;
P1=a[time%10];
P2=a[time/10];
}
}
elsebz=~bz;
}