1. 程式人生 > >基於51微控制器的電子時鐘(數碼管顯示)

基於51微控制器的電子時鐘(數碼管顯示)

     此次對於數碼管進行一個簡單的應用,同時可以設計一個電子小時鐘,增加趣味性。

首先我們先進行原理圖的講解,這裡我們直接使用的開發板,其原理連線圖如下:





其中D(0~1)是連線在微控制器的P0口上的。

   從圖中,我們可以看到,第一個74HC573是來控制8個數碼管的位選的,就是說我要選種哪個數碼管,這裡的WE是低電平有效,比如說我想選中最後一個數碼管,那麼這裡我就要將0x7f送到相應的I/O口。第二個74HC573是來控制數碼管顯示什麼的這裡0~9的16進位制碼如下:

0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f;

要想完成電子時鐘,我們先要顯示一個數值,

這裡我們封裝兩個函式:

wirte_address(unsigned char);

write_date(unsigned int);

第一個函式是用來寫地址的,就是用來選中數碼管的;

第二個函式是用來寫資料的,就是選中的數碼管顯示什麼。

比如我們想在最後一個數碼管上顯示一個8;

那麼則有:

write_address(0x7f);

write_date(0x7f);

這樣就能在相應的位置上顯示一個8了;


   然後我們就要多個位置顯示,這裡我們硬體的P0口接的是數碼管,同時我們要引進相應的延時函式delay(unsigned int);

我們利用發光管的餘輝和人眼視覺暫留作用,讓人眼無法分辨出來,從而達到“同時顯示的效果”。

但是我們需要注意的是消影,在每次寫入之前令P0=0xff,這是為了消除上次段選資料,否則會造成,顯示混亂。


  當我們能顯示時,就需要了解定時器,讓它來計時,然後將數值取出,進行顯示。這裡我們的晶振是12MHz,所以一個機械週期時1/12MHz=1us,為了使計時較為精確,我們這裡選擇定時器0的模式2,8位重灌定時器,並且我們100us進入一次中斷,定時器的初始化就該如下:

TMOD=0x02;

TH0=256-100;

TL0=256-100;

EA=1;

ET0=1;

TR0=1;


    這樣我們再定義一個n用來計數進入中斷的次數,當n的10000時,就表示1s到了,所以我們需要對相應的變數進行處理。

     那麼我們需要對資料進行處理,比如,所得的秒的值,其十位=秒/10,其個位就等於秒%10,其它以此類推。


那麼整個的程式程式碼如下:

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};	 //數碼管位選資料
sbit dula=P2^6;//段選訊號,寫數碼管資料
sbit wela=P2^7;//位選訊號,選擇數碼管

uint miao=0;		//秒
uint fen=0;			//分
uint shi=0;		    //時
uint n=0;			//計數
uint date[6]={0,0,0,0,0,0};	  //定義一個有6個地址的陣列,分別存時,分,秒的個位和十位。
void delay(uint z)			 //延時函式
{
     uint x,y;
	 for(x=z;x>0;x--)
	  for(y=50;y>0;y--);
}

void write_address(uchar address)		 //寫地址函式,選擇數碼管
{
    wela=1;
	P0=address;
	wela=0;
}

void write_date(uint n)				     //寫資料函式,送入段選訊號
{
     dula=1;
	 P0=table[n];
	 dula=0;
}										//顯示函式
void display()
{	 	 
       write_date(date[0]);
      P0=0xff;
      write_address(0x7f);
       delay(1);


     write_date(date[1]);
	 P0=0xff;
	 write_address(0xbf);
	 delay(1);

	 write_date(date[2]);
	 P0=0xff;
	 write_address(0xef);
	 delay(1);
	 

	 write_date(date[3]);
	 P0=0xff;
	 write_address(0xf7);
	 delay(1);

	 write_date(date[4]);
	 P0=0xff;
	 write_address(0xfd);
	 delay(1);


	 write_date(date[5]);
	 P0=0xff;
	 write_address(0xfe);
	 delay(1);

	 
}
void time_init()						   //定時器初始化函式
{
    TMOD=0x02;							  //選擇方式2
	TH0=156;							  //重灌初值為156
	TL0=156;							  //執行值為156
	EA=1;								  //開總中斷
	ET0=1;								  //開定時器0中斷
	TR0=1;								  //開定時器0
}

void main()
{
   dula=0;								   //先關閉位選,段選訊號。
   wela=0;
   time_init();
   while(1)
   {
       display();
   }

    
}



void timer() interrupt 1					  //定時器0中斷
{
     n++;
	 if(n==10000)								 //當n=10000時,表示1s到了
	 {	 
	     n=0;
	     miao++;
		 if(miao==60)
		 {
		     miao=0;
		     fen++;
			 if(fen==60)
			 {
			     fen=0;
				 shi++;
				 if(shi==24)
				 {
				    shi=0;
				 }
			 }
		 }
		 date[0]=miao%10;
		 date[1]=miao/10;
		 date[2]=fen%10;
		 date[3]=fen/10;
		 date[4]=shi%10;
		 date[5]=shi/10;
	
	 }

	  
}

其效果圖如下: