教你如何用51单片机轻松玩转数码管


今天教大家如何操纵数码管,教程简单易懂,非常适合小白享用。
(本教程操作演示基于清翔家的51开发板,其他开发板注意IO接口的焊接即可)

数码管的静态显示

静态显示的特点是每个数码管的段选必须接一个8位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。

数码管的应用场景

数码管在我们的生活中用途广泛,它成本低、耗电少,在工业生产和家庭生活等领域扮演这重要角色。
温湿度计:Alt!
万年历

数码管显示原理

Alt
改图为数码管的原理图,单个数码管由8个LED灯组成,每个LED灯都对应一个引脚,我们将其中一个LED的正负极两端通上电,那么该灯就会点亮。点亮多个LED,形成一些特定的组合,就形成数字。

Alt

数码管分为共阴极数码管共阳极数码管,共阳极就是数码管中所有LED正极接同一个正极,共阴极同理,与之相反。

数码码表

既然我们已经讲过数字的产生是靠同时点亮多个数码管来产生组合,那究竟如何来实现就要涉及二进制的知识了,我们来详细看一下。

一个字节由8个位组成,正好对应上了我们一个数码管8个LED灯。
我们以共阴极数码管为例:
学习流水灯的时候,我们都知道,编程时1代表高电平0代表低电平,当我们给LED灯对应二进制位置1时,该LED灯便会点亮。8个位保存的信息一起送给数码管,数码管就显示出数字了。

具体的对应关系如下图:

Alt

1代表点亮0代表熄灭
由上图我们知道,abcdef点亮,
gh熄灭,组成为数字0,将该二进制写成十六进制为0x3f
利用同样的道理,我们可以表示出其他的数字或符号,它们便组成了数码码表,编程时将数码码表组装成数组会非常方便。

unsigned char code leddata[]={ 
 
                0x3F,  //"0"
                0x06,  //"1"
                0x5B,  //"2"
                0x4F,  //"3"
                0x66,  //"4"
                0x6D,  //"5"
                0x7D,  //"6"
                0x07,  //"7"
                0x7F,  //"8"
                0x6F,  //"9"
                0x77,  //"A"
                0x7C,  //"B"
                0x39,  //"C"
                0x5E,  //"D"
                0x79,  //"E"
                0x71,  //"F"
                0x76,  //"H"
                0x38,  //"L"
                0x37,  //"n"
                0x3E,  //"u"
                0x73,  //"P"
                0x5C,  //"o"
                0x40,  //"-"
                0x00,  //熄灭
                0x00  //自定义
 
                         };

位选和段选

假如一个LED灯对应一个IO口,一个数码管对应8个IO口,那么8个数码管就对应64个IO口。这太占用单片机的IO资源,51总共40个IO口,哪里来这么多。

这就需要借助锁存器来实现对IO口的控制了,这就涉及位选和段选的概念了。

Alt

上图展示的为锁存器的电路图,在这里不详细讲述它的原理,详情参考这篇文章:

74HC573

我们在这里需要弄明白的是如何去编程操作。
位选确定激活哪个数码管
操作方法跟上述相同,例0xfe(1 1 1 1 1 1 1 0)点亮第一个数码管,有区别的是,0为激活数码管,这个大家可以自己动手操作一下。
段选确定点亮哪个LED灯

代码实现

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

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
void main()//main函数自身会循环
{
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110 选通第一位数码管
	WE = 0;//锁存位选数据

	DU = 1;//打开段选锁存器
	P0 = 0X06;//0000 0110 显示“1”
	DU = 0;//锁存段选数据
	
	while(1);
}  

数码管的动态显示

动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。

动态与静态大体上是一样的,区别在于我们需要不断地刷新数码管,最简单的方法就是放在while循环中。

话不多说,直接上代码,大家慢慢理解。

#include <reg52.h>//包含51头文件
#include <intrins.h>//包含移位标准库函数头文件

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选

//共阴数码管段选表0-9
uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};

/*====================================
函数	: delay(uint z)
参数	:z 延时毫秒设定,取值范围0-65535
返回值	:无
描述	:12T/Fosc11.0592M毫秒级延时
====================================*/
void delay(uint z)
{
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 

/*====================================
函数	:display(uchar i)
参数	:i 显示数值,取值范围0-255
返回值	:无
描述	:三位共阴数码管动态显示
====================================*/
void display(uchar i)
{
	uchar bai, shi, ge;
	bai = i / 100; //236 / 100  = 2
	shi = i % 100 / 10;	//236 % 100 / 10 = 3
	ge  = i % 10;//236 % 10 =6
	
	//第一位数码管  		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[bai];//
	DU = 0;//锁存段选数据
	delay(5);

	//第二位数码管
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFD; //1111 1101
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[shi];//
	DU = 0;//锁存段选数据
	delay(5);

	//第三位数码管
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFB; //1111 1011
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[ge];//
	DU = 0;//锁存段选数据
	delay(5);
}

void main()//main函数自身会循环
{	
	while(1)
	{
		display(236); //数码管显示函数
	}	
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值