基于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;
	
	 }

	  
}

其效果图如下:








©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页