十分详细的数码管电子时钟(基于51单片机)

数码管由于内部由多段LED灯构成,也被称为多段式LED数码管
从数码管里面包含的LED个数来分,可以分为七段式、八段式、十四段式等。

七段式数码管:
在这里插入图片描述

八段式数码管(比七段式右下角多了一个小点):
在这里插入图片描述
十四段式数码管:
在这里插入图片描述
从数码管电极性质来分可分为共阴数码管(CC)共阳数码管(AC)
共阴数码管内部所有的LED灯段的负极接在了一起,只需要给相应位高电平即可点亮一段。
共阳数码管只需给低电平即可点亮一段。

以八段共阳数码管为例:
在这里插入图片描述
A,B,C,D,E,F,G,DP分别对应数码管上的一段。

在程序中我们给A,G,D三段置低电平,点亮这三段数码管。

#include <reg52.h>

sbit a = P2^0;
sbit b = P2^1;
sbit c = P2^2;
sbit d = P2^3;
sbit e = P2^4;
sbit f = P2^5;
sbit g = P2^6;
sbit dp = P2^7;

void main()
{
	a = 0;
	b = 1;
	c = 1;
	d = 0;
	e = 1;
	f = 1;	
	g = 0;	
	dp = 1; 
	while(1);  
}

(在这里我没有给单片机接晶振部分的时钟电路以及其他基本电路,是因为在proteus里面其实不需要接也能正常工作,仿真就是仿真,与实际工程中还是有很大的区别的,在实际过程中是一定要接的)
在这里插入图片描述
(如果你的数码管直接接在P0口没有亮的话是正常的,P0口要加上拉电阻做普通输入输出口)

看到这里也许会有小伙伴发出疑问:“51单片机总共就4组32个IO口,你控制一个八位数码管就要一组8位IO口,那不是最多就能控制4个八位数码管吗?怎么实现数码管电子时钟的效果呢?”。

孙大圣有了金箍棒才能战无不胜攻无不克成为斗战胜佛,我们也要找一个“金箍棒”来帮我们完成“西天取经”。
我们的“金箍棒”:74hc573,一个8位数据锁存器。
在这里插入图片描述
引脚功能描述:

引脚 功能
OE(Output Enable,低电平有效) 输出使能
1D~8D 8位数据输入
1Q~8Q 8位数据输出
LE(Latch Enable,高电平有效) 锁存使能

74hc573功能表:
在这里插入图片描述
第一行/第二行:OE=0、LE=1时,输出端数据等于输入端数据。
第三行:OE=0、LE=0时,输出端数据保持为上一次数据不变。
第四行:OE=1,无论其他是高电平低电平,输出端为高阻态。

#include <reg52.h>
#include <intrins.h>

sbit LE = P3^0;    //Ëø´æʹÄܶË
sbit OE = P3^1;		 //Êä³öʹÄܶË

//¹²Ñô¹ÜÊýÂë¹Ü±àÂë±í£º¶ÔÓ¦0~F
unsigned char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

void Delay1000ms()		//@11.0592MHz£¬ÀûÓÃSTC-ISP×Ô¶¯Éú³É±È½Ï¾«È·µÄÒ»ÃëÑÓʱ
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	unsigned int i = 0;
	LE = 1;			//Ëø´æʹÄÜ
	OE = 0;			//Êä³öʹÄÜ
	while(1)
	{
		P2 = table[i];
		Delay1000ms();
		i++;
		if(i > 15)
			i = 0;
	}
}

(第一次用GIF截屏工具,等到数码管回复到0还走了两下我再按的停止,这个程序绝对没有问题,狗头)
在这里插入图片描述
进行到这一步,这个数码管时钟你已经掌握了一大部分了,只需要再坚持一下就会出成果了。然而现在还存在的问题是,虽然完成了动态显示,但是似乎IO口还是少了,如果按这样的接线方式来看的话,那么在下一步,我们将解决这个问题。
既然一个数码管满足不了我们的要求,我们换一个多位数码管集成的元件:7SEG-MPX6-CC是7段六位共阴级数码管,通过给123456这几位低电平来点亮对应的位。
在这里插入图片描述
时钟的每一个位的是一直动态变化的,如果直接一次把123456这几位都打开那么数码管六个位显示的数据都一样,就像:
在这里插入图片描述
显然不是我们时钟想要的效果。
这时候就引进我们的段选和位选的概念。
段选就是选择数码管7段亮哪些段。
位选就是选择六位数码管中亮哪一位。
用很短的时间来完成6位数码管的依次显示,就是我们数码管时钟最精髓的思想了。

#include <reg51.h>
#include <intrins.h>

sbit LE = P3^0;    //Ëø´æʹÄܶË
sbit OE = P3^1;		 //Êä³öʹÄܶË

sbit w1 = P3^2;    //λѡ
sbit w2 = P3^3;
sbit w3 = P3^4;
sbit w4 = P3^5;
sbit w5 = P3^6;
sbit w6 = P3^7;

//¹²Òõ¹ÜÊýÂë¹Ü±àÂë±í
unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 9;
	j = 244;
	do
	{
		while (--j);
	} while (--i);
}


void Timer0Init(void)		 //³õʼ»¯¶¨Ê±Æ÷0£¬50ms½øÒ»´ÎÖжÏ
{
	TMOD &=0X0F;
  TMOD |=0x01;
  TH0 = (65536 - 50000)/256;
  TL0 = (65536 - 50000)%256;
  EA = 1; 	   
  ET0 = 1;	   
  TR0 = 1;	   
}

static unsigned int j = 0;
unsigned int s1 = 5,s2 = 5,m1 = 9,m2 = 5,h1 = 3,h2 = 2;   //23:59:55ʱ¼ä

void main()
{
	Timer0Init();
	LE = 1;			//Ëø´æʹÄÜ
	OE = 0;		//Êä³öʹÄÜ
	while(1)
	{	
		
		w1=0;w2=1;w3=1;w4=1;w5=1;w6=1;
		P2 = table[h2];
		Delay5ms();

		w1=1;w2=0;w3=1;w4=1;w5=1;w6=1;
		P2 = table[h1]+0x80;   //¼Ó0x80ÏÔʾСÊýµã£¬·Ö¸ôСʱ·ÖÖÓÃëÖÓ
		Delay5ms();

		w1=1;w2=1;w3=0;w4=1;w5=1;w6=1;
		P2 = table[m2];
		Delay5ms();

		w1=1;w2=1;w3=1;w4=0;w5=1;w6=1;
		P2 = table[m1]+0x80;
		Delay5ms();
		
		w1=1;w2=1;w3=1;w4=1;w5=0;w6=1;
		P2 = table[s2];
		Delay5ms();

		w1=1;w2=1;w3=1;w4=1;w5=1;w6=0;
		P2 = table[s1];
		Delay5ms();



	}
}


void interruptTimer0() interrupt 1     //Öжϴ¦Àíʱ¼ä½øλ
{
	ET0 = 0;	   
  TR0 = 0;
	TH0 = (65536 - 50000)/256;
  TL0 = (65536 - 50000)%256;
	j++;
	if(j >= 20)
	{
		s1++;
		j = 0;
		if(s1 > 9)
		{
			s1 = 0;
			s2++;
			if(s2 > 5)
			{
				s2 = 0;
				m1++;
				if(m1 > 9)
				{
					m1 = 0;
					m2++;
					if(m2 > 5)
					{
						m2 = 0;
						h1++;
						if(h2 < 2)
						{
							if(h1 > 9)
							{
								h1 = 0;
								h2++;
							}
						}
						else
						{
							if(h1 > 3)
							{
								h1 = 0;
								h2 = 0;
								m1 = 0;
								m2 = 0;
								s1 = 0;
								s2 = 0;
							}
						}
					}
				}
			}
		}
	}	
	ET0 = 1;	   
  TR0 = 1;
}

在这里插入图片描述
(这里秒没有显示出来,是刷新率太短,要加延时,但是在proteus里面我试了很多值,要么显示秒钟有明显的一位一位亮起来的感觉,要么就不显示,大家也可以帮我解决一下)
在实际中不会出现这种不亮的情况,只会亮度低,如果亮度低了就加延时,若果肉眼分辨的出每位亮起的时间差就减少延时。

OK,祝大家五一劳动节快乐。

原创文章 6 获赞 5 访问量 553

猜你喜欢

转载自blog.csdn.net/lqj11/article/details/105869187