LED數碼管秒錶(精確到0.01s)

利用C51單片機實現LED數碼管顯示秒錶。主要使用到的結構是51單片機的三個P口以及定時器。

要求:

製作一個LED數碼管顯示的秒錶,用2位數碼管顯示計時時間,最小計時單位爲"十毫秒",計時範圍爲0.01-9.99s.當第一次按下並鬆開計時功能鍵時,秒錶開始計時並顯示時間;第二次按下並鬆開計時器功能鍵,停止計時,計算兩次按下計時功能鍵的時間,並在數碼管上顯示;第三次按下計時功能鍵,秒錶清零,再按一次計時功能鍵,重新開始計時。如果計時到9.99s時將停止計時,按下計時功能鍵,秒錶清零,再按下重新開始計時。

分析:

既然要的是三位數字那麼一定要的就是三個7段數碼管了,剛開始可能看着這麼多的功能可能會感到很複雜,實際上我們從本質上來看,就是說如果不按鍵就是卡主不動,按一下就會一直走,一直走到9.99然後停止(這個時候再按一下就會清零) 按第二下就會停下來,停在當前計數的時間,按第三下就會歸零回到從來沒有按過的狀態。從這裏也可以分析處理9.99秒停止的時候的狀態實際上也是按第二下的狀態,再按一下就歸零。這樣看起來就沒有那麼的複雜,但是還是有些繞,我們的全局變量中當中實際上要做的就是把0-999的數字記錄下來的一個值,一個記錄下按鍵次數的值,再一個記錄下中斷次數的值。
代碼如下:

//P0口作爲I/O端口輸出時,輸出級屬於開漏電路,必須外接10KΩ上拉電阻
#include <reg51.h>
unsigned char code discode1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//一共十個數,code關鍵字是意味着存儲到ROM當中去。
unsigned char code discode2[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//上面(有小數點)和下面(無小數點)都是從0到9的字節碼
unsigned char code discode3[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//第三個數
unsigned char times=0;//中斷了多少次
int second;//一共經歷的時間,這裏要注意的是如果你要記錄的數據較大就不能夠用char和unsigned char來定義,否則就無法表示
unsigned char key=0;
void main(void)
{
	TMOD=0x01;
	ET0=1;//允許TO進行中斷
	EA=1;
	second=0;//初值賦值爲0
	P0=discode1[second/100];//顯示對應的秒位
	P2=discode2[second/10-(second/100)*10];//顯示對應的後面
	P1=discode3[second%10];
	while(1)
	{
		if((P3&0x80)==0x00)//正常情況下爲1,但開關按下去爲0,此處僅僅對P3.7口做了一個判斷P3^7?
		{
			while((P3&0x80)==0x00);//如果你不鬆開就一直保持在這個循環裏面,不改變狀態繼續之前的中斷操作	
		   key++;
		   switch(key)
		   {
			case 1://第一次按鍵,啓動計時
				   TH0=0xee;//一次爲5ms的中斷
				   TL0=0x00;
				   TR0=1;//啓動定時器的必備條件
				   break;
			case 2:
				TR0=0;//暫停計時
				break;
			case 3://第三下清零,並將次數設置爲1
				key=0;
				second=0;//設置秒數爲零
				P0=discode1[second/100];//顯示對應的秒位
				P2=discode2[second/10-(second/100)*10];//顯示對應的後面
				P1=discode3[second%10];
				break;
		   }
		   //while((P3&0x80)==0x00){};//按鍵時間過長在此循環,不添加此步一會又要返回到判斷過程中,		  



		}



	}
	

}
void timer() interrupt 1 using 0
{
	TR0=0;//停止計時,在設置時間的時候就不計時了,會存在一定誤差,在這裏暫停說明剛纔的中斷T0已經溢出,所以後續操作首先要對其進行賦初值
	TH0=0xee;
	TL0=0X00;
	times++;	
	 if(times==2)//2x5ms=10ms是0.01s
	 {
	 	times=0;
		second++;//0.01爲單位的數量+1
		P0=discode1[second/100];//顯示對應的秒位
		P2=discode2[second/10-(second/100)*10];//顯示對應的後面
		P1=discode3[second%10];//0.01位顯示
	 }
	if(second==999)//當滿了的時候,這個時候停止就好了
	{
	 	TR0=0;
		//TH0=0xee;
		//TL0=0x00;
		second=0;
		key=2;//用程序設置按鍵次數爲第二次因爲下次再按下去就是第三次清零,符合題目要求
	}
	else
	{

		TR0=1;//否則開中斷繼續計時
	}



}

代碼註釋已經分析的很詳細了,再提醒一下就是對應的記錄次數的變量要找一個>999範圍的例如int型,雖然很簡單的問題但是很容易忽視。

接下來就是proteus電路瞭如下所示,()要注意的是P0口作爲I/O端口輸出時,輸出級屬於開漏電路,必須外接上拉電阻(圖中用的是一個阻排(RESPACK))否則高電平就無法輸出。還有就是數碼管是選擇共陰極(cathnode)的而非共陽極(anode)的
在這裏插入圖片描述

元器件:

在這裏插入圖片描述

存在的問題(已解決):

我不太明白爲什麼AT89C51單片機爲什麼可以在不接外部晶振的情況下工作,因爲我查到的網上資料都是說不能不接外部晶振的,然而此處的電路沒有接卻照樣可以正常運行。

問題解決:

51單片機實際上是必須要有一個外部的晶振的,但是在proteus當中是可以省略的,因爲這個仿真程序已經自動幫我添加了對應的晶振,要改變的話可以右擊51單片機然後點擊edit property 有一個clock frequency就是對應的晶振頻率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章