14.动态数码管的使用

工作原理:
动态显示的特点是将所有的位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。这样一来,就没有必要每一位数码管配一个锁存器,从而大大简化了硬件电路。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余晖和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态要差一点。
前四个数码管分别显示1234的程序:

#include<STC15F2K60S2.H>
void Delayms(int ms);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;   //初始化程序,关闭蜂鸣器继电器LED
	while(1)
	{
		P2=0XC0;				//打开数码管位选573锁存器
		P0=0X01;				//选中第一个数码管
		P2=0XE0;				//打开数码管段选573锁存器
		P0=0XF9;  			//使数码管显示1
		Delayms(1);				//1ms的延迟几乎不能分辨出来
		
		P2=0XC0;				//打开数码管位选573锁存器
		P0=0X02;				//选中第二个数码管
		P2=0XE0;				//打开数码管段选573锁存器
		P0=0XA4;  			//使数码管显示2
		Delayms(1);
		
		P2=0XC0;				//打开数码管位选573锁存器
		P0=0X04;				//选中第三个数码管
		P2=0XE0;				//打开数码管段选573锁存器
		P0=0XB0;  			//使数码管显示3
		Delayms(1);
		
		P2=0XC0;				//打开数码管位选573锁存器
		P0=0X08;				//选中第四个数码管
		P2=0XE0;				//打开数码管段选573锁存器
		P0=0X99;  			//使数码管显示4
		Delayms(1);
	}
}
void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

数码管99秒倒计时程序:

#include<STC15F2K60S2.H>
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
unsigned char num=99;
unsigned int i=0;

void Delayms(int ms);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;			//关闭蜂鸣器继电器LED
	while(1)
	{
		i++;
		if(i==500)			//由于下面的两个数码管一共延时2ms,故循环500次即1s数码管变化一次
		{
			i=0;
			if(num==0)num=100;		//计时结束,重新计时
			num--;
		}
		
		P2=0XC0;				//打开数码管位选537锁存器
		P0=0X01;				//选中第一个数码管
		P2=0XE0;				//打开数码管段选537锁存器
		P0=tab[num/10];	//数码管显示十位的数字
		Delayms(1);
		
		P2=0XC0;				//打开数码管位选537锁存器
		P0=0X02;				//选中第二个数码管
		P2=0XE0;				//打开数码管段选537锁存器
		P0=tab[num%10];	//数码管显示个位的数字
		Delayms(1);
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

数码管99秒倒计时程序,用定时器延迟。

#include<STC15F2K60S2.H>
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
unsigned char num=99;
unsigned char tt=0;

void Delayms(int ms);
void Timer0Init(void);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;			//关闭蜂鸣器继电器LED
	//初始化配置定时器0
	Timer0Init();
	ET0=1;
	EA=1;
	
	while(1)
	{
		P2=0XC0;				//打开数码管位选537锁存器
		P0=0X01;				//选中第一个数码管
		P2=0XE0;				//打开数码管段选537锁存器
		P0=tab[num/10];	//数码管显示十位的数字
		Delayms(1);
		
		P2=0XC0;				//打开数码管位选537锁存器
		P0=0X02;				//选中第二个数码管
		P2=0XE0;				//打开数码管段选537锁存器
		P0=tab[num%10];	//数码管显示个位的数字
		Delayms(1);
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

void Timer0Init(void)		//5毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void Timer0(void) interrupt 1
{
	tt++;
	if(tt==200)
	{
		tt=0;
		if(num==0)num=100;
		num--;
	}
}

此程序实现了用定时器0来进行数码管计时间隔1s的延时,而扫描的1ms仍使用了软件延时。
大致思路:我们可以看到原来的程序是在主函数中,计数循环次数,循环500次即1s,操作使num自减,而此程序是在定时器中定时1s,定时到了num自减。其核心思想都是使num每1s自减1。
数码管99秒倒计时程序,调用子函数(第一种方法)

#include<STC15F2K60S2.H>
unsigned char num=99;
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
unsigned int i=0;
unsigned char yi,er;

void Display(unsigned char yi,unsigned char er);
void Delayms(int ms);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;			//关闭蜂鸣器继电器LED
	while(1)
	{
		i++;
		if(i==500)
		{
			i=0;
			if(num==0)num=100;				//计时结束,重新计时
			num--;
		}
		yi=num/10;
		er=num%10;
		Display(yi,er);
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

void Display(unsigned char one,unsigned char two)
{
	P2=0XC0;			//打开数码管位选573锁存器
	P0=0X01;			//选中第一个数码管
	P2=0XE0;			//打开数码管段选573锁存器
	P0=tab[one];		//显示十位
	Delayms(1);
	
	P2=0XC0;			//打开数码管位选573锁存器
	P0=0X02;			//选中第二个数码管
	P2=0XE0;			//打开数码管段选573锁存器
	P0=tab[two];		//显示个位
	Delayms(1);
}

数码管99秒倒计时程序,调用子函数(第二种方法)

#include<STC15F2K60S2.H>
unsigned char num=99;
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
unsigned int i=0;

void Display(unsigned char sum);
void Delayms(int ms);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;			//关闭蜂鸣器继电器LED
	while(1)
	{
		i++;
		if(i==500)
		{
			i=0;
			if(num==0)num=100;				//计时结束,重新计时
			num--;
		}
		Display(num);
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

void Display(unsigned char sum)
{
	P2=0XC0;			//打开数码管位选573锁存器
	P0=0X01;			//选中第一个数码管
	P2=0XE0;			//打开数码管段选573锁存器
	P0=tab[sum/10];		//显示十位
	Delayms(1);
	
	P2=0XC0;			//打开数码管位选573锁存器
	P0=0X02;			//选中第二个数码管
	P2=0XE0;			//打开数码管段选573锁存器
	P0=tab[sum%10];		//显示个位
	Delayms(1);
}

8个数码管的程序,前2位仍然99秒倒计时,其他位依次为345678

//8个数码管的程序,让前两位仍然99秒倒计时,其他位分别显示345678
#include<STC15F2K60S2.H>
unsigned char num=99;
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
unsigned int i=0;
unsigned char yi,er,san,si,wu,liu,qi,ba;

void Delayms(int ms);
void Display1(unsigned char yi,unsigned char er);
void Display2(unsigned char san,unsigned char si);
void Display3(unsigned char wu,unsigned char liu);
void Display4(unsigned char qi,unsigned char ba);

void main(void)
{
	P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;			//关闭蜂鸣器继电器LED
	while(1)
	{
		i++;
		if(i==125)
		{
			i=0;
			if(num==0)num=100;
			num--;
		}
		yi=num/10;
		er=num%10;
		san=3;si=4;wu=5;liu=6;qi=7;ba=8;
		Display1(yi,er);
		Display2(san,si);
		Display3(wu,liu);
		Display4(qi,ba);
	}
}

void Delayms(int ms)
{
	int i,j;
	for(i=0;i<ms;i++)
		for(j=845;j>0;j--);
}

void Display1(unsigned char yi,unsigned char er)
{
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X01;				//选中第一个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[yi];			//显示yi对应的数值
	Delayms(1);
	
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X02;				//选中第二个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[er];			//显示er对应的数值
	Delayms(1);
}

void Display2(unsigned char san,unsigned char si)
{
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X04;				//选中第三个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[san];		//显示san对应的数值
	Delayms(1);
	
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X08;				//选中第四个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[si];			//显示si对应的数值
	Delayms(1);
}

void Display3(unsigned char wu,unsigned char liu)
{
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X10;				//选中第五个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[wu];			//显示wu对应的数值
	Delayms(1);
	
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X20;				//选中第六个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[liu];		//显示liu对应的数值
	Delayms(1);
}

void Display4(unsigned char qi,unsigned char ba)
{
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X40;				//选中第七个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[qi];			//显示qi对应的数值
	Delayms(1);
	
	P2=0XC0;				//打开数码管位选537锁存器
	P0=0X80;				//选中第八个数码管
	P2=0XE0;				//打开数码管段选537锁存器
	P0=tab[ba];			//显示ba对应的数值
	Delayms(1);
}

由上可知,想要哪一位显示哪一个值,即可在主函数中相应的对变量赋值,例如:想要第三个显示8,即san=8(也可以为一个可求出值的表达式,如上程序中yi=num/10)
:通过观察我们可以发现,主函数和子函数中均有yi,er,san…它们是否冲突是否会被认为是重复定义?实则不然,在C语言中变量分为整体变量和局部变量,且局部变量优先于整体变量,也就是当我们在子函数和主函数中都定义了yi,那么在子函数过程中,yi遵循的是子函数的定义,而主函数对它的定义在子函数中是无效的。当然,在仅有主函数定义而没有子函数定义时,即便它在子函数中,也一定遵循主函数的定义,为整体变量。

猜你喜欢

转载自blog.csdn.net/qq_44628230/article/details/104339532