ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【单片机技术】—— 数码管的动态显示方法与定时器

2020-03-14 12:01:29  阅读:292  来源: 互联网

标签:动态显示 P0 WELA 数码管 void DULA 单片机 uint


上一篇 BlogBlogBlog 主要记录了一些简单的外部中断和定时器的使用,在那个时候我们还只会让指定的数码管显示同一个数字,在这篇博文中,我们就记录一下几种让不同数码管显示不同数字(也叫做动态显示)的办法。

文章目录

一、动态显示思路的萌芽

我们试想:因为现在我们不是只会一次只能显示某一个数字嘛,那么,如果我们实现这样的效果:(以下描述规定在某一时刻只能亮一个数码管)第一秒第一个数码管亮“1”,第二秒第二个数码管亮 “2”、、、第六秒第六个数码管亮“6”,接着重复上面的循环。

如果间隔的时间不是1s,而是几毫秒甚至几微秒,那么人眼就会分辨不出来,看起来就像是同一时间6个数码管分别显示 “123456” 的效果。

我们可以如何实现上述思想呢?—— 通过定时器!我们可以让定时器计时,每到了规定时间,就往后移动一位。下面,我们看看代码部分:

1.1 代码和实验部分

代码如下:

#include<reg52.h>
#define uchar unsigned char   //宏定义
#define uint unsigned int

sbit WELA = P2^7;   //定义位选
sbit DULA = P2^6;   //定义段选

uchar number,position,t;
//number表示需要显示什么数,position表示数字显示的位置,t 表示定时器计时时间

uchar code table_DUAN[] = {0x06,0x5b,0x4f,
                           0x66,0x6d,0x7d,0x07,
                           0x7f,0x6f,0x77,0x7c,
                           0x39,0x5e,0x79,0x71};  //定义段选信号编码表(从1开始)

uchar code table_WEI[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //定义位选信号编码表

void init();   //初始化函数,完成诸如启动定时器、赋初值等一系列操作

void main()
{
	init();
	while(1)
	{
  		if(t == 1)      
 		{
   			t = 0;
   			if(number == 6)     //因为我们最多显示到6
   			{
    				number = 0;
   			}
   			if(position == 6)  
   			{
    				position = 0;
   			}

   			DULA = 1;
   			P0 = table_DUAN[number];
  			DULA = 0;
   			number++;
 
   			P0 = 0xff;   //为了防止前面的段选信号在一瞬间会对下面的位选信号产生影响
 
   			WELA = 1;
   			P0 = table_WEI[position];
   			WELA = 0;
   			position++;
  	       }
 	}
}

void init()
{
	t = 0;
 	number = position = 0;

	TH0 = (65536-1000)/256;
	TL0 = (65536-1000)%256;

	TMOD = 0x01;

	EA = 1;
	ET0 = 1;

	TR0 = 1;
}

void timer0() interrupt 1
{
 	TH0 = (65536-1000)/256;
 	TL0 = (65536-1000)%256;
 	t++;
}

二、用delay()函数实现任意数字的显示

不过,大家注意到了吗:用上面的代码,如果想显示任意给定的数字,那么似乎有些麻烦,下面我们介绍一种通用方法:

如果给定了一个数字(假设是两位数),那么,我们可以直接把它的每一位(比如个位、十位、、、)分离出来,然后在一个while(1) 大循环里面显示了十位、延迟一小段时间,又去显示个位,再延迟一段时间。在这样的无限循环中,我们肉眼看到的就是“静止”的两位数了。

注意:如果想显示的是三位数,那么uchar类型就不再适用了,因为 uchar最大就是256,需要使用int

2.1 代码和实验部分

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

sbit WELA = P2^7;
sbit DULA = P2^6;

uchar t,temp,shi,ge;

uchar code table_DUAN[] = {0x06,0x5b,0x4f,
            0x66,0x6d,0x7d,0x07,
            0x7f,0x6f,0x77,0x7c,
            0x39,0x5e,0x79,0x71}; 

void delay(uint);

void main()
{
	temp = 45;
 	shi = temp/10;
 	ge = temp%10;

	while(1)
	{
		DULA = 1;
  		P0 = table_DUAN[shi-1];
		DULA = 0;
		
		P0 = 0xff;

		WELA = 1;
  		P0 = 0xfe;
  		WELA = 0;

		delay(5);

		DULA = 1;
  		P0 = table_DUAN[ge-1];
  		DULA = 0;

		P0 = 0xff;

		WELA = 1;
  		P0 = 0xfd;
  		WELA = 0;

		delay(5);
	}
}

void delay(uint z)
{
 	uint x,y;
 	for(x=z;x>0;x--)
  		for(y=100;y>0;y--);
}

三、进阶部分

如果你觉得只是单纯显示一个数不够过瘾,那么我们现在看一个有趣的例子:我们给定一个数字,让这个数字每隔一秒减少一次,当减到100的时候,我们就让数码管保持在100这个数

那么,这个题目我们就可以通过第二节讲到的利用 delay() 显示任何数,以及定时器定时1s控制递减

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

sbit WELA = P2^7;
sbit DULA = P2^6;

uchar t,bai,shi,ge;
uint temp;

uchar code table_DUAN[] = {0x3f,0x06,0x5b,0x4f,
            		   0x66,0x6d,0x7d,0x07,
            		   0x7f,0x6f,0x77,0x7c,
            		   0x39,0x5e,0x79,0x71}; 

void init();
void delay(uint);
void display(uint temp);

void main()
{
 	init();
 	temp = 145;
 	while(1)
 	{
  		if(t == 20)     //每经过1s,数字就递减一次
  		{
   			t = 0;
   			temp--;
   			if(temp == 100)    
   			{
    				TR0 = 0;   //当减小到100时,我们把计数器关了,他自然就不会递减
   			}
  		}
  		display(temp);   //普通的动态显示,和第二节类似,只不过我们现在把它封装在了函数里面   
 	}
}

void init()
{
 	WELA = 0;
 	DULA = 0;
 	
 	t = 0;
 	TH0 = (65536-50000)/256;
 	TL0 = (65536-50000)%256;
 	
 	TMOD = 0x01;
 	
 	EA = 1;
 	ET0 = 1;
 	
 	TR0 = 1;
}

void delay(uint z)
{
 	uint x,y;
 	for(x=z;x>0;x--)
  		for(y=100;y>0;y--);
}

void display(uint temp)
{
 	bai = temp/100;
 	shi = (temp-100*bai)/10;
 	ge = temp%10;

 	DULA = 1;
 	P0 = table_DUAN[bai];
 	DULA = 0;

	P0 = 0xff;

	WELA = 1;
	P0 = 0xfe;
	WELA = 0;

	delay(1);

 	DULA = 1;
 	P0 = table_DUAN[shi];
 	DULA = 0;

	P0 = 0xff;

 	WELA = 1;
 	P0 = 0xfd;
 	WELA = 0;

	delay(1);

	DULA = 1;
 	P0 = table_DUAN[ge];
	DULA = 0;

	P0 = 0xff;

	WELA = 1;
 	P0 = 0xfb;
 	WELA = 0;
 	
	dealy(1);

void timer0() interrupt 1
{
 	TH0 = (65536-50000)/256;
 	TL0 = (65536-50000)%256;
 	t++;
}

【补充二】:我们现在想实现这样的功能:数码管一开始显示765410,用定时器 T0 控制,每隔1s递减1次,同时,T0控制LED 以每隔0.5s的速度控制流水灯。当 765410递减到 765398 的时候让数码管保持现在的值,同时流水灯停止,并且全部闪烁,当闪烁持续3s之后,数码管显示 “HELLO”

这个题目的代码我晚点会上传到github,继续贴在着就有点长了。

好啦,这就是本次 BlogBlogBlog 的全部内容啦!我们学习了数码管的动态操作,对定时器的使用进一步深化,希望能够大家带来帮助!

标签:动态显示,P0,WELA,数码管,void,DULA,单片机,uint
来源: https://blog.csdn.net/weixin_44586473/article/details/104854498

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有