近年來隨著科學技術的發展,單片機的應用正在不斷走下面還深入。本文簡單闡述了基于單片機的數字秒表的的設計。本設計的主要特點是計時精度達到0.01秒,是各種體育競賽的必要設備之一。
本設計的數字秒表采用AT89S52單片機為主要器件,利用其定時器的原理,結合顯示電路、LED數碼管以及外部外部中斷電路來設計計時器。將軟硬件結合起來,使得系統能實現0~99.99秒的計時,計時精度位0.01秒。硬件系統利用proteus仿真,在仿真中就能觀察到系統的實際運行情.
一 硬件設計
1、1 總體方案的設計
數字秒表具有顯示直觀、讀取方便、精度高等優點,在計時中廣泛應用。本設計中用單片機和數碼管組成數字秒,表力求結構簡單。
設計中包括硬件電路的設計和系統程序的設計。硬件電路主要有主控制器、控制按鈕與顯示電路組成。主控制器采用單片機AT89S52,顯示電路采用四位共陰極數碼管顯示計時時間。
本設計利用AT89S52單片機的定時器,使其能精確計時。利用中斷系統使其實現啟動和暫停的功能,P0口輸出段碼數據,P2.0~P2.2連上譯碼器作為位選,P3.2和P3.3接口的兩個按鈕分別實現啟動和暫停功能。設計的基本要求是正確性。硬件電路按下圖進行設計。
本地圖片,請重新上傳
計時器采用T0中斷實現,定時溢出中斷周期為1ms,當溢出中斷后向CPU發出溢出中斷請求,每發出10次中斷請求就對10ms位(即最后一位)加一,達到100次就對100ms位加一,以此類推,直到99.99s為止。
再看按鍵的處理。兩個按鍵采用中斷的方法,設置外部中斷0和外部中斷1位脈沖邊沿觸發方式,這樣一來每當按鍵按下時便會觸發中斷,從而實現啟動和暫停。
1.2 單片機的選擇
本設計在選取單片機時,充分借鑒了許多成型產品使用單片機的經驗。并根據自己的實際情況,選用了ATMEL公司的AT89S52。
ATMEL公司的89系列單片機以其卓越的性能、完善的兼容性、快捷便利的電擦寫操作、低廉的價格完全替代了87C51/62和8751/52,低電壓、低功耗,有DIP、PLCC、QFP封裝,是目前性能最好、價格最低、最受歡迎的單片機之一。
AT89S52為40腳雙列直插封裝的8位通用微處理器,采用工業標準的C51內核,在內部功能及管腳排布上與通用的8XC52相同,其主要用于匯聚調整時的功能控制。功能包括對匯聚主IC內部寄存器、數據RAM及外部接口等功能部件的初始化,匯聚調整控制,匯聚測試圖控制等。
單片機外部結構
AT89S52單片機采用40腳的DIP封裝,如下所示。
本地圖片,請重新上傳
(1)主電源引腳Vss和Vcc
a、 Vss接地
b、 Vcc正常操作時為+5V接地
外接晶振引腳XTAL1和XTAL2
a、XTAL1內部振蕩電路反相放大器的輸出端,是外接晶體的一個引腳。當采用外部振蕩時,此引腳接地。
b、XTAL2內部振蕩電路反相放大器的輸出端,是外接晶體的的另一端。當采用外部振蕩時,此引腳接外部振蕩源。
(2)控制或與其他電源復用引腳
a、RST/VPD 當振蕩器運行是,在此引腳上出現兩個機器周期的高電平(由低到高跳變),將使單片機復位在Vcc掉電期間,此引腳可接上備用電源,由VPD向內部提供備用電源,
以保持內部RAM中的數據。
b、ALE/PROG 正常操作時為ALE功能(允許地址鎖存)提供把地址的低字節鎖存到外部存儲器,ALE引腳以不變的頻率(振蕩器頻率的1/6)周期性的發出正脈沖信號。因此,它可以用作對外輸出的時鐘,或用于定時目的。
c、PSEN 外部程序存儲器讀選通信號輸出端,在從外部程序存儲取指令(或數據)期間,PSEN在每個機器周期內兩次有效。
d、EA/Vpp 內部程序存儲器和外部程序存儲器選擇端。當EA/Vpp位高電平時,訪問內部程序存儲器,當EA/Vpp為低電平時,則訪問外部程序存儲器。對于EPROM編程期間,此引腳上加21VEPROM編程電源(Vpp)。
(3)輸入/輸出引腳P0.0~P0.7,P1.0~P1.7,P2.0~P2.7,P3.0~P3.7。
a、P0口(P0.0~P0.7)是一個8位漏極開路型雙向I/O口,在訪問外部存儲器時,它是分時傳送的低字節地址和數據總線,P0口能以吸收電流的方式驅動八個LSTTL負載。
b、P1口(P1.0~P1.7)是一個帶有內部上拉電阻的8位準雙向I/O口。能驅動四個LSTTL負載。
c、P2口(P2.0~P2.7)是一個帶有內部上拉電阻的8位準雙向I/O口,在訪問外部存儲器時,它輸出高8位地址。P2口可以驅動四個LSTTL負載。
d、P3口(P3.0~P3.7)是一個帶有內部上拉電阻的8位準雙向I/O口。能驅動四個LSTTL負載。
1.3 顯示電路的選擇與設計
對于數字顯示電路,通常采用液晶顯示或數碼管顯示。對于一般的段式液晶屏,需要專門的驅動電路,而且液晶顯示作為一種被動顯示,可視性差,不適合遠距離觀看;對于具有驅動電路和單片機接口的液晶顯示模塊,一般多采用并行接口,對單片機的接口要求較高,占用資源多;另外,AT89S52單片機本身沒有專門的液晶驅動接口。而數碼管作為一種主動顯示器件,具有亮度高、響應速度快、價格便宜、易于購買等優點,而且有遠距離視覺效果,很適合夜間或者遠距離操作。因此在本設計中,我們采用7段數碼管作為顯示介質。
數碼管顯示可以分為靜態顯示和動態顯示兩種。由于本設計需要采用四位數碼管顯示時間,如果靜態顯示則占用的口線多,硬件電路復雜,所以采用動態顯示。
動態顯示是一位一位地輪流點亮各位數碼管,這種逐位點亮顯示器的方式稱為位掃描。通常各位數碼管的段選線相應并聯在一起,由一個8位的I/O口控制;各位的公共陰極位選線由另外的I/O口線控制。動態方式顯示時,各數碼管輪流選通,要使其穩定顯示必須采用掃描方式,即在某一時刻只選通一位數碼管并送出相應的段碼,在另一時刻選通另一數碼管,并送出相應的段碼,依次規律循環,即可以使各位數碼管顯示將要顯示的字符,雖然這些字符是在不同時刻分別顯示,但由于人眼存在視覺暫留效應,只要每位顯示間隔足夠短就可以給人同時顯示的感覺。
本地圖片,請重新上傳
1.4系統總體電路的設計
系統總體電路如下圖所示
AT89S52單片機為主電路的核心部分,各個電路均與單片機相連,由單片機統籌協調各個電路的運行工作。
開始鍵和暫停鍵使用了外部中斷,所以需要連到單片機的P3.2和P3.3引腳上,這兩個I/O口的第二功能是單片機的外部中斷0端口和外部中斷1端口。
顯示電路由四位數碼管組成,采用動態顯示方式,因此有8位段控制和4位位控制,8位段接控制接P0口,P0.0~P0.7分別控制數碼管的a b c d e f g dp顯示,位控制接在P2.0和P2.1兩個口,在通過一個2—4譯碼器實現位控制。
本地圖片,請重新上傳
二 軟件設計
2.1主程序設計
本系統程序主要模塊由主程序、定時中斷服務程序、外部中斷0服務程序和外部中斷1服務程序組成。其中主程序是整個程序的主體。可以對各個中斷程序進行調用。協調各個子程序之間的關系。
主程序主要是設置定時器大的工作模式,對定時器賦初值,開總中斷、兩個外部中斷以及定時器溢出中斷。并設置外部中斷為脈沖邊沿觸發方式。
2.2中斷程序設計
本方案中用到了三個中斷:外部中斷0、外部中斷1和定時器T0溢出中斷。CPU在響應中斷時,先處理高級中斷,后處理低級中斷,若有多個同級中斷時,則應按自然優先順序處理。例如當CPU正在處理一個中斷申請時,又出現了另一個優先級比它高的中斷請求,這時,CPU就暫停對當前優先級較低的中斷源的服務,轉去響應優先級比它高的中斷請求,并為其服務。待服務結束,再繼續執行原來較低級的中斷服務程序。而當CPU為級別高的中斷服務程序服務時,如果級別低的中斷發出中斷請求,此時CPU是不會響應的,所以為了避免開始和暫停兩個按鍵中的一個出現沒有響應的情況,在進行編程是要注意中斷的使用,避免出現中斷的嵌套。合理分配中斷對本設計是很重要的。
(1)外部中斷0服務程序
外部中斷0服務程序結合外部P3.2鍵實現數字秒表的啟動功能。流程如下圖所示。
本地圖片,請重新上傳
(2)外部中斷1服務程序
外部中斷1服務程序結合外部P3.3鍵實現數字秒表的停止功能。
流程圖如下所示。
本地圖片,請重新上傳
(3)定時器T0中斷服務程序
當T0一處后,向CPU發出中斷請求信號。CPU跳轉到定時中斷程序執行,具體流程如下。
2.3程序清單
#include<reg52.h>
unsigned int data table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //顯示碼值
unsigned int i,j,k,l,count;
void delay(unsigned int z) //延時程序
{
unsigned int x,y;
for(x=z;x!=0;x--)
for(y=110;y!=0;y--);
}
void main()
{
TMOD=0x01; //設置定時器為模式1
TH0=(65536-1000)/256; //給定時器賦定時初值
TL0=(65536-1000)%256;
EA=1; //開中斷
EX0=1;
EX1=1;
ET0=1;
IT0=1; //設置外部中斷位脈沖邊沿觸發方式
IT1=1;
while(1) // 數碼顯示
{
P2=0x03;
P0=table[i];
delay(1);
P2=0x02;
P0=table[j];
delay(1);
P2=0x01;
P0=(table[k]+0x80);
delay(1);
P2=0x00;
P0=table[l];
delay(1);
};
}
void ex0() interrupt 0 //外部中斷0
{
TR0=1; //開定時器,開始計數
}
void ex1() interrupt 2 //外部中斷0
{
TR0=0; //停止計數
}
void timer0() interrupt 1 //定時器T0溢出中斷
{
TH0=(65536-1000)/256; //重裝計數初值
TL0=(65536-1000)%256;
count++; //溢出中斷次數加一
if(count==10)
{
count=0;
i++; //溢出10次,0.01s位加一
if(i==10)
{
i=0; //0.01s位到10了,清零,0.1s位加一
j++;
if(j==10)
{
j=0; //0.1s位到10了,清零,1s位加一
k++;
if(k==10)
{
k=0; //1s位到10了,清零,10s位加一
l++;
}
}
}
}
}