51单片机实验04 -数码管的动态显示实验

目录

一、实验目的

二、实验内容

三、实验原理

四、实验方法

五,实验效果及代码

1,效果

2,代码

六,课后习题

1,使用定时器T0的中断函数1 从999999~0计时

 1)效果

2)代码

2,使用定时器T1的中断函数3 从999999~0计时

1)效果 

2)代码


一、实验目的


1、熟悉掌握数码管动态显示的基本方法。
2、根据已知电路和设计要求在实验板上实现数码管动态显示。
3、掌握利用定时器T0中断的使用方法。


二、实验内容

在KST-51开发板上,选择任意左右相连的4位数码管,利用定时器T0中断实现动态显示0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容


三、实验原理


实验要求“4位数码管上实现动态显示

0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容”。动态扫描可以实现该要求。

简单地说,动态扫描就是选通一位,送一位数据。原理图中的LEDS0-LEDS5是相应数码管的位选信号,即选择哪个数码管显示数字;P0.0-P0.7是段码,即要显示的数字。可以通过依次选通某一位7段数码管并通过P0端口送出显示数据。由于人眼的视觉残留原理,如果这种依次唯一选通每一位7段数码管的动作在10ms内完成,就会造成多位数码管同时点亮显示各自数字的假象。
本实验使用定时器T0中断,实现每2s更新一次数字。

定时器有关代码请看前面文章:

51单片机实验03-单片机定时/计数器实验-CSDN博客


四、实验方法


1、根据电路图,分析和掌握数码管动态显示的原理,选择4位数码管。使用定时器T0中断实现每2秒更新一次数字的设计思路。
本次实验使用Timer0中断,由于其定时时间最大为65536us,不能实现2s的长延时,那么可以使用多次中断来实现,并且在中断到来时,不断地死循环显示数字,即根据动态显示原理“选通一位,来一位数据”。设x表示千位的数字,由于最大的数字为9,则(x%10)、(x+1)%10、(x+2)%10、(x+3)%10分别是千位、百位、十位、个位上的数字。在编写代码时,设置Timer0定时时间为2ms,可以用一个参数cnt计算中断的次数;当中断的次数达到1000次时,说明已经达到了2s,此时更新数字,即将数字x自增1。
2、针对要求,画出程序流程图,根据流程图进行代码编写。
3、编译调试生成HEX文件,进行代码烧写,完成数码管动态显示功能。


五,实验效果及代码

我选择的是中间四个数码管,如果想要选择其它数码管的,可以修改这几行代码:

addr2,addr1,addr0分别控制了138译码器的输出y0~y6,因为y6已经用来控制发光二极管 ,因此,y0~y5就是用来控制数码管的。例如,y0控制最右边的数码管leds0,对应的138译码器输入:

addr2=0;addr1=0;addr0=0;

如果想要控制最左边的数码管,就需要y5输出低电平。即addr2=1;addr1=0;addr0=1;

1,效果

0123-1234等数字的循环显示

2,代码

#include<reg52.h>
sbit enled=P1^4;   // 138译码器使能  
sbit addr3=P1^3;
sbit addr2=P1^2;
sbit addr1=P1^1;
sbit addr0=P1^0;  // 使能端					  
	unsigned  char  code ledChar[]={	 // 数码管0~9真值表
   0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
//,0x88,0x83,0xC6,0xA1,0x86,0x8E
};

				  

	unsigned char ledBuff[]={    // 数码管全灭
	0xFF,0xFF,0xFF,0xFF
	};		 
	unsigned int outflow=0;  // 记录定时器溢出次数
	unsigned char  ind=0;  // 动态扫描的索引
	unsigned char flags=0;  // 2s定时标志
void  main(){
	unsigned long sectransistor=0;  // 记录数码管显示的秒数

    enled=0;
	addr3=1;
	TMOD=0x01;  // 定时器T0选择模式1(16位定时器)
	TH0=0xFC;   // 定时器的初始值
	TL0=0x67; 

	EA=1;   //总中断打开
	ET0=1;  // 定时器0使能中断打开

	TR0=1;      // 定时器T0运行
	while(1){  	 // 写好定时器中断服务后再使用while循环
		if(flags==2){	 // flags是2s定时
		 flags=0;   // 重新计时,直到flags再次等于1(时间再次为2s)
		ledBuff[0]=ledChar[(sectransistor+3)%10];	 
		ledBuff[1]=ledChar[(sectransistor+2)%10];
		ledBuff[2]=ledChar[(sectransistor+1)%10];  // 0+1对10取余为1 ,10对10取余为0
		ledBuff[3]=ledChar[sectransistor%10]; // 最左边的晶体管数值最小0
		sectransistor++;  // 秒数自增
		
		}
	
	}
	
		}

	void  InterruptTimer0() interrupt 1{	  // 定时器T0中断服务函数1
	TH0=0xFC;   // 定时器初始值
	TL0=0x67; 
	outflow++;	// 溢出自增
	if(outflow==2000){		 //每隔2s切换显示内容
	   outflow=0;
	   flags=2;  // 2s到了之后,flags立起来
	
	}
		P0=0xFF;  // 关闭段
	 switch(ind){   // 控制指定晶体管亮起
	  case 0:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[0];break;
	  case 1:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[1];break;
	  case 2:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[2];break;
	  case 3:addr2=1;addr1=0;addr0=0;ind=0;P0=ledBuff[3];break;
	  default: break;
	  }
	}



六,课后习题

 需要知道的是,使用不同的定时器,所对应的中断函数也是不一样的,如下表中所示👇

 可以看到,定时器T0的中断函数编号是1 ,而定时器T1的中断函数3,因此在写程序的时候需要正确更改interrupt后面的编号。

1,使用定时器T0的中断函数1 从999999~0计时

 1)效果

效果同T1定时器👇:

定时器T1使用中断函数从999999~0计时

2)代码

#include<reg52.h>
sbit enled=P1^4;   // 138译码器使能  
sbit addr3=P1^3;
sbit addr2=P1^2;
sbit addr1=P1^1;
sbit addr0=P1^0;  // 使能端					  
//	unsigned  char  code ledChar[]={	 // 数码管真值表
//0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
//0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
//};

				   //倒计时	    0x8E,0x86,0xA1,0xC6,0x83,0x88,  
    unsigned char  code ledChar[]={	  // 从数值9开始		  
	0x90,0x80,0xF8,0x82,0x92,0x99,0xB0,0xA4,0xF9,0xC0
	
	
	};
	unsigned char ledBuff[]={    // 数码管全灭
	0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF
	};		 
	unsigned int outflow=0;  // 记录定时器溢出次数
	unsigned char  ind=0;  // 动态扫描的索引
	unsigned char flags=0;  // 1s定时标志
void  main(){
	unsigned long sectransistor=0;  // 记录数码管显示的秒数
//  0~999999
    enled=0;
	addr3=1;
	TMOD=0x01;  // 定时器T0选择模式1
	TH0=0xFC;   // 定时器的初始值
	TL0=0x67; 

	EA=1;   //总中断打开
	ET0=1;  // 定时器0使能中断打开

	TR0=1;      // 定时器T0运行
	while(1){  	 // 写好定时器中断服务后再使用while循环
		if(flags==1){	 // flags是1s定时
		 flags=0;   // 重新及时,直到flags再次等于1
		ledBuff[0]=ledChar[sectransistor%10];	 // 开启指定晶体管	
		ledBuff[1]=ledChar[sectransistor/10%10];
		ledBuff[2]=ledChar[sectransistor/100%10];
		ledBuff[3]=ledChar[sectransistor/1000%10];
		ledBuff[4]=ledChar[sectransistor/10000%10];
		ledBuff[5]=ledChar[sectransistor/100000%10];
		
		sectransistor++;  // 数码管在之前的基础上+1s
		
		}
	
	}
	
		}

	void  InterruptTimer0() interrupt 1{	  // 定时器T0中断服务函数1
	TH0=0xFC;   // 定时器初始值
	TL0=0x67; 
	outflow++;	// 溢出自增
	if(outflow==1000){		 //1s
	   outflow=0;
	   flags=1;  // 1s到了之后,flags立起来
	
	}
		P0=0xFF;  // 关闭段
	 switch(ind){   // 控制指定晶体管亮起
	  case 0:addr2=0;addr1=0;addr0=0;ind++;P0=ledBuff[0];break;
	  case 1:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[1];break;
	  case 2:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[2];break;
	  case 3:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[3];break;
	  case 4:addr2=1;addr1=0;addr0=0;ind++;P0=ledBuff[4];break;	
	  case 5:addr2=1;addr1=0;addr0=1;ind=0;P0=ledBuff[5];break;
	  default: break;
	  }
	
	}



2,使用定时器T1的中断函数3 从999999~0计时

1)效果 

定时器T1使用中断函数从999999~0计时

2)代码

#include<reg52.h>
sbit enled=P1^4;   // 138译码器使能  
sbit addr3=P1^3;
sbit addr2=P1^2;
sbit addr1=P1^1;
sbit addr0=P1^0;  // 使能端					  
//	unsigned  char  code ledChar[]={	 // 数码管真值表
//0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
//0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
//};

				   //倒计时	    0x8E,0x86,0xA1,0xC6,0x83,0x88,
    unsigned char  code ledChar[]={
	 0x90,0x80,0xF8,0x82,0x92,0x99,0xB0,0xA4,0xF9,0xC0
	
	
	};
	unsigned char ledBuff[]={    // 数码管全灭
	0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF
	};		 
	unsigned int outflow=0;  // 记录定时器溢出次数
	unsigned char  ind=0;  // 动态扫描的索引
	unsigned char flags=0;  // 1s定时标志
void  main(){
	unsigned long sectransistor=0;  // 记录数码管显示的秒数
//  0~999999
    enled=0;
	addr3=1;
	TMOD=0x10;  // 定时器T1选择模式1
	TH1=0xFC;   // 定时器初始值
	TL1=0x67; 

	EA=1;   //总中断打开
	ET1=1;  // 定时器1使能中断打开

	TR1=1;      // 定时器运行
	while(1){  	 // 写好定时器中断服务后再使用while循环
		if(flags==1){	 // flags是1s定时
		 flags=0;   // 重新及时,直到flags再次等于1
		ledBuff[0]=ledChar[sectransistor%10];	 // 开启指定晶体管	
		ledBuff[1]=ledChar[sectransistor/10%10];
		ledBuff[2]=ledChar[sectransistor/100%10];
		ledBuff[3]=ledChar[sectransistor/1000%10];
		ledBuff[4]=ledChar[sectransistor/10000%10];
		ledBuff[5]=ledChar[sectransistor/100000%10];
		
		sectransistor++;  // 数码管在之前的基础上+1s
		
		}
	
	}
	
		}

	void  InterruptTimer1() interrupt 3{	  // 定时器0中断服务函数
	TH1=0xFC;   // 定时器初始值
	TL1=0x67; 
	outflow++;	// 溢出自增
	if(outflow==1000){		 //1s
	   outflow=0;
	   flags=1;  // 1s到了之后,flags立起来
	
	}
		P0=0xFF;  // 关闭段
	 switch(ind){   // 控制指定晶体管亮起
	  case 0:addr2=0;addr1=0;addr0=0;ind++;P0=ledBuff[0];break;
	  case 1:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[1];break;
	  case 2:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[2];break;
	  case 3:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[3];break;
	  case 4:addr2=1;addr1=0;addr0=0;ind++;P0=ledBuff[4];break;	
	  case 5:addr2=1;addr1=0;addr0=1;ind=0;P0=ledBuff[5];break;
	  default: break;
	  }
	
	}



有问题请在评论区留言,一天8h在线。

  • 12
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C51单片机数码管动态显示单片机基础教学中比较经典的一个实验,该实验可以通过单片机控制数码管的显示,实现数字的动态滚动、计时、计数等功能。下面是该实验的总结。 一、实验原理 数码管动态显示是通过单片机的高速刷新来实现的。数码管的显示是静态的,即只有一次性地将数码管的显示数据送入数码管的存储器中,而动态显示则是通过不断地刷新数码管的显示数据,使其看上去是在不停地变化。单片机控制数码管的显示,需要通过端口输出控制信号,将位选和段选信号送入数码管中,从而实现数码管动态显示。 二、实验器材 1. C51单片机开发板 2. 74HC595移位寄存器 3. 共阴数码管 4. 面包板、杜邦线等 三、实验步骤 1. 将数码管的阳极连接到单片机的P2口,将数码管的阴极连接到74HC595移位寄存器的输出端Q0~Q7。 2. 将74HC595移位寄存器的SCK、RCK、SDA分别连接到单片机的P3.5、P3.6、P3.7口。 3. 在程序中设置数码管的显示数据,将其存入74HC595移位寄存器中。 4. 设置位选信号,将控制信号送入数码管中,实现数码管动态显示。 四、实验代码 以下是C语言编写的数码管动态显示实验代码: ``` #include <reg52.h> #define uchar unsigned char #define uint unsigned int uchar code table[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90}; //数码管显示表 void delay(uint x) { uint i, j; for (i = x; i > 0; i--) for (j = 110; j > 0; j--); } void main() { uchar i = 0; while (1) { P3 = 0xFF; //清零P3口 P1 = table[i++]; //设置数码管显示数据 if (i == 10) i = 0; //循环显示0~9 P3 = ~(1 << i); //设置位选信号,显示第i个数码管 delay(1); //延时一段时间 } } ``` 五、实验结果 实验成功后,数码管应该可以进行动态滚动、计时、计数等功能的实现。通过对程序进行修改,还可以实现更多有趣的功能,如闪烁、渐变等。 六、实验结论 通过本次实验,我们掌握了单片机控制数码管动态显示原理和方法,了解了74HC595移位寄存器的使用方法。在实验中,我们不仅学会了如何通过单片机控制数码管的显示,还锻炼了编程能力和动手能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值