51单片机编程应用(C语言):数码管

news2025/2/5 0:51:24

目录

1.数码管原理

一位数码管引脚定义:

四位一体数码管:

多个数码管同时显示不同数字 

51单片机的数码管的原理图

51单片机实现静态显示和动态显示

静态显示:

 动态显示:


1.数码管原理

一位数码管引脚定义:

数码管是由8个LED组成的,其中共阴极数码管是8个LED共用一个阴极;共阳极数码管是8个LED共用一个阳极;每个数码管灯由图中左下角的8段LED构成,分别是ABCDEFG以及DP;正好和1个字节的8位相对应;从图中也可以看出,8段LED中,每段LED对应的引脚图,即每段LED和引脚之间的连接关系,基本是按照就近原则来连接的,比如A段,A段的正极连接3和8引脚(在共阳极数码管的情况下),A段的负极连接7号引脚;以此类推,其他引脚关系都可从图中看出来。

值得注意的是,我们开发板上的连接方式是共阴极连接。
如果想要使这个数码管显示数字“6”,该怎么操作呢?需要让A、F、E、D、C、G都亮起来即可。那么如何使A、F、E、D、C、G都点亮,其他的熄灭呢?参照上面的图可知,对于共阴极连接方式,首先3和8引脚都是要接地的(即负极、低电平、0);然后A、F、E、D、C、G都接正极(高电平,1),B和DP接负极,这样就能得到一个数字“6”,即A、B、C、D、E、F、G、DP设置为1011 1110;

下面为proteus仿真视频

proteus单个数码管仿真

实现9到0依次循环,代码如下 :

#include <REGX52.H>
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}
void main()	
{
	while(1)
	{
		P2=0x6F;
		Delay(500);
		P2=0x7F;
		Delay(500);
		P2=0x07;
		Delay(500);
		P2=0x7D;
		Delay(500);
		P2=0x6D;
		Delay(500);
		P2=0x66;
		Delay(500);
		P2=0x4F;
		Delay(500);
		P2=0x5B;
		Delay(500);
		P2=0x06;
		Delay(500);
		P2=0x3F;
		Delay(500);
		
		
	}
}

因为我是P2-7接的是G,P2-6接的是F..........反过来的,所以根据上面的引脚图要反着来计算二进制的值。

四位一体数码管:

可以看到,以共阴极数码管为例,每个数码管共用阴极,但是四个数码管阳极所有的对应引脚都是连接同一个引脚;例如这四个数码管的A段LED都是连接在一起的,和11引脚相连;这四个数码管的B段LED都是连接在一起的,和7引脚相连。这样做的好处是节省单片机的引脚,如图中有4*8=32个LED段,但是只用12个引脚就可以了。
对于这种数码管,如果想让第三位数码管显示一个数字1,怎么操作?

因为是共阴极,所以12、9、8、6正常来讲都是负极才能点量对应的数码管。要想达到只第三个数码管显示1的目的:其中引脚12、9、6这三个阴极都置为1(高电平),这样第一、二、四个数码管就都不会亮;将引脚8设置为0(低电平),这样第三个数码管就有了电路连通的条件;然后再将B断和C段对应的引脚置为高电平,即7和4引脚置为1(高电平),此时就能第三个数码管中的B和C段对应的LED灯就亮了,其他段的灯不亮,即达到了只第三个数码管显示1的目的。

proteus仿真如下:

代码是P2=0x60;我这里P2.7接的是A,根据这两个例子,P2的值赋值是不是要看数码管的A,B,C,D.....与P2的8个引脚怎么接才行,这里P2.7接A,依次下去,亮一,就赋值P2=0x60。

比如P2.0接A,亮1就赋值0x06,所以一定要看自己的单片机原理图是如何接的,还要看是共阴极还是共阳极,

下面我就给出两种情况显示各个数字的值(小数点dp都不点亮)(共阴极数码管)

第一种:P2.0接A,依次接下去,(例如视频所示)

第二种:P2.7接A,依次接下去:(例如上面图所示) 

0  :  0xFE     1:     0x60         2:      0xDA       3:       0xF2        4: 0x66       5:         0xB6  

6   :   0xBE     7  :     0xD0       8:      0xFE       9:        

多个数码管同时显示不同数字 

 

关于上面讲到的,这四个数码管四个数码管阳极所有的对应引脚都是连接同一个引脚,这样导致的结果是,如果我们想让第二个数码管和第三个数码管同时点亮,且第二个和是第三个数码管显示不同的数字,是无法做到的,因为即使为了让第二个数码管亮而将9号引脚置为0,那么此时9和8引脚都为0,7和4引脚都为1,结果是第二个二极管和第三个二极管都显示数字1,无法达到显示不同数字的目的;所以因为四个二极管对应段LED都共用同一个引脚,导致的结果是只能显示同样的数字。

那么如何使不同的数码管显示不同的数字呢?这就是我们的目标2要实现的了,即动态数码管显示;利用的原理是人眼的视觉暂留和数码管显示的余晖原理;比如我们想达到让前三个数码管分别显示“1”“2”“3”的目的,经过上面的理论我们可以知道让三个数码管同时显示三个不同的数字是不可能的,但是我们可以让第一个数码管显示数字1,然后迅速的让第二个数码管显示数字2,然后迅速的让第三个数码管显示数字3,这要他们的间隔足够短,在我们视觉上看起来就像是同时在显示1、2、3一样。

#include <REGX52.H>

//数码管段码表
unsigned char NixieTable[]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xD0,0xFE,0xF6};

//延时子函数
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
	switch(Location)		//位码输出
	{
		case 1:P0_0=1;P0_1=1;P0_2=1;P0_3=1;break;//4个数码管都不选
		case 2:P0_0=1;P0_1=1;P0_2=1;P0_3=0;break;//选择第四个数码管
		case 3:P0_0=1;P0_1=1;P0_2=0;P0_3=1;break;//选择第三个数码管
		case 4:P0_0=1;P0_1=1;P0_2=0;P0_3=0;break;//选择第3和第4个数码管
		case 5:P0_0=1;P0_1=0;P0_2=1;P0_3=1;break;//选择第二个数码管
		case 6:P0_0=1;P0_1=0;P0_2=1;P0_3=0;break;//选择第2和第4个数码管
		case 7:P0_0=1;P0_1=0;P0_2=0;P0_3=1;break;//选择第2和第3个数码管
		case 8:P0_0=1;P0_1=0;P0_2=0;P0_3=0;break;//选择第2和第3和第4个数码管
		case 9:P0_0=0;P0_1=1;P0_2=1;P0_3=1;break;//选择第一个数码管
		case 10:P0_0=0;P0_1=1;P0_2=1;P0_3=0;break;//选择第1和第4个数码管
		case 11:P0_0=0;P0_1=1;P0_2=0;P0_3=1;break;//选择第1和第3个数码管
		case 12:P0_0=0;P0_1=1;P0_2=0;P0_3=0;break;//选择第1和第3和第4个数码管
		case 13:P0_0=0;P0_1=0;P0_2=1;P0_3=1;break;//选择 1 2 号数码管
		case 14:P0_0=0;P0_1=0;P0_2=1;P0_3=0;break;//选择1 2 4  号数码管
		case 15:P0_0=0;P0_1=0;P0_2=0;P0_3=1;break;//选择1 2 3 号数码管
		case 16:P0_0=0;P0_1=0;P0_2=0;P0_3=0;break;//四个数码管全选
	}
	P2=NixieTable[Number];	//段码输出
	Delay(1);				//显示一段时间
	P2=0x00;				//段码清0,消影
}

void main()
{
	while(1)
	{
		Nixie(9,1);		//在数码管的第1位置显示1
//		Delay(20);
		Nixie(5,2);		//在数码管的第2位置显示2
//		Delay(20);
		Nixie(3,3);		//在数码管的第3位置显示3
//		Delay(20);
		Nixie(2,0);	
	}
}

注意: 虽然我switch case 把所有的情况都列出来了,也就是位选的所有情况,但是,动态扫描时,一个数码管是显示一位数字,所以尽量要选择单个数码管,代码中的case9 5 3 2。如果你选中的是多个数码管,那么他只会显示相同的数字,而且,你选中多个数码管时,main语句时要注意不要重复选中相同的数码管,比如不能同时选择case7 8,否则会出错,下图所示是选择4个数码管一起亮,显示5:

 代码是:Nixie(16,5);

上面是用了C语言的数组,和switch case语句,调用函数,我们讲一下数组就OK了,switch case 还是很好理解的

 有了这些基础,我们看看51单片机的数码管的相关原理图

51单片机的数码管的原理图

 

显然,8个数码管的位选(选择哪一个数码管亮)由单片机3个引脚控制,这样的好处大大缩小了引脚的数量,不用每一个LED对应一个引脚。下面我们讲一讲38译码器电路。

38译码器是三个线到八个线的译码器;其实就是负责将三个输入A、B、C(P22-P24)转成八个输出Y0-Y7(也对应LED1-8);A、B、C三个输入值分别表示为三个二进制的数(C为高位,B为中位,A为低位,即数字组成为CBA),这三个输入值,转换成十进制,就对应他们的输出。

例如输入A为0,B为0,C为0,则输入为000,其对应的十进制值是0,即Y0有效,其他无效(低电平为有效,高电平位无效),所以Y0是0,Y1-Y7为1;

再例如,如果输入A为1,B为0,C为0,则输入为001(CBA,前面说了,C为高位,B为中位,A为低位),其对应的十进制为1,即Y1有效,其他无效(低电平为有效,高电平位无效),所以Y1是0,Y0和Y2-Y7为1;刚好对应我们的8个数码管,
以此类推。。。。

其真值表如下所示

有了这些知识,比如我们要选中第三个数码管亮,LED(1~8)的值是 

对应38译码器是不是 101  P2_4=1,P2_3=0,P2_2=1,即可

下面我们再来看数74HC245(双向据缓冲器)

根据原理图我们是不是知道,数码管的段选都与这个芯片连接,即晶体管的正极是接在74HC245(双向数据缓冲器)上的。为什么不直接接在CPU上呢?还要多此一举呢?

因为单片机的高电平驱动能力太弱,这个缓存器提高驱动能力。这样单片机的I/O口就变成了控制信号,不需要很高的电流驱动,把数据给了这个芯片之后,这个芯片有VCC给他供电,就很好的驱动数码管,亮度得到了保证。

DIR的高低电平决定了数据的流向;在74HC245中,如果将DIR,也就是LE(1引脚)设置为高电平,则表示数据流向为从左边到右边。由下图可知,A0对应B0,A1对应B1,以此类推;而B0-B7对应LCD0-7;

总结一下说就是,输入给P00-P07什么数据,该数据就原封不动的送给LCD0-LCD7。 

电容的作用:给VCC滤波,稳定电源,确保电路稳定性。提高电路工作性能。

电阻:限流

  74HC245作用:双向的数据缓冲 

51单片机实现静态显示和动态显示

静态显示:

第二个数码管显示5

第一步是选择使哪个晶体管点亮:即要让目标点亮的等负极有效,而负极是接在138译码器上的,138译码器的8输出连接着静态数码管的负极,138译码器的3个输入连接着MCU的引脚(P22-P24口);所以我们要通过对P22-P24口的设置,来控制目标晶体管负极有效。

第二步是设置该目标点亮的晶体管具体显示什么数字;即通过对正极引脚的设置,控制具体LED的8段LED哪几段点亮,用以生成目标数字。晶体管的正极是由74HC245的P00-P07等8个引脚来输入的;

总结:

  • 第一步,选择哪个晶体管点亮,控制引脚为P22-P24;
  • 第二步,选择具体点亮的数字,控制引脚为P00-P07;
#include <REGX52.H>

void main()	
{
	while(1)
	{
		P2_2=0;
		P2_3=1;
		P2_4=0;
		
		
		P0_0=1;
		P0_1=0;
		P0_2=1;
		P0_3=1;
		P0_4=1;
		P0_5=1;
		P0_6=1;
		P0_7=0;
		
	}
}

最后,我们可以对代码进行完善,写一个函数,两个入参分别为:第一个参数为第几个等亮,第二个参数为显示什么数字,这样就能通过调用该函数时,传入参数的不同,控制不同的灯显示不同的数字,代码如下: 

#include <REGX52.H>

//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

//数码管显示子函数
//Location表示第几个数码管点亮;Number表示该数码管显示什么数字
void Nixie(unsigned char Location,Number)
{
	switch(Location)		//位码输出
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];	//段码输出
}

void main()
{
	Nixie(2,5);	//在数码管的第3位置显示数字6
	while(1)
	{
		
	}
}

 动态显示:

实现动态数码管的方法和代码,即如果想让第一个数码管显示1,第二个数码管显示2,第三个数码管显示3,且让他们同时显示;方法就是先让第一个显示1,然后立马让第二个显示2,再立马让第三个显示3;只要他们之间的间隔足够短,在我们视觉效果上看来就是在同时显示。

代码如下

#include <REGX52.H>

//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

//延时子函数
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
	switch(Location)		//位码输出
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];	//段码输出
	Delay(1);				//显示一段时间
	P0=0x00;				//段码清0,消影
}

void main()
{
	while(1)
	{
		Nixie(1,1);		//在数码管的第1位置显示1
//		Delay(20);
		Nixie(2,2);		//在数码管的第2位置显示2
//		Delay(20);
		Nixie(3,3);		//在数码管的第3位置显示3
//		Delay(20);
	}
}

其中的P0=0x00;表示每次循环结束时都将所有的数码管进行清零,即全部熄灭,免得留下灯的残影。

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1427097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea查看日志的辅助插件 --- Grep Console (高亮、取消高亮)

&#x1f680; 分享一款很有用的插件&#xff1a;Grep Console &#x1f680; 我们在查看日志的时候可能会有遗漏&#xff0c;使用这款插件可以让特定的关键词高亮&#xff0c;可以达到不遗漏的效果&#xff01; 如果你是一个开发者或者对日志文件分析感兴趣&#xff0c;不要…

linux搭建jupyter

查看虚拟环境 conda info --envs进入虚拟环境 conda activate my_env pip install jupyter pip install ipykernel1. jupyter notebook启动 1.1 创建临时jupyter notebook任务 jupyter notebook --ip0.0.0.0 --no-browser --allow-root --notebook-dir/home/xxx1.2 jupyter…

Xcode报fatal error: ‘XXX.h‘ file not found

在Xcode中遇到 "fatal error: XXX.h file not found" 的错误通常是由于缺少头文件或头文件路径配置不正确导致的。 以下仅为我的解决方案&#xff1a; 1.点击项目名——>显示此页面 2.选择Build Settings——>输入 Search Paths 3. 点击空白处添加路径 4…

使用浏览器开发工具分析性能

使用浏览器开发工具分析性能 一、网络分析二、性能分析 一、网络分析 1、面板概览&#xff1a; Controls (控件) : 控制面板的功能Filters (过滤器) : 控制在请求列表中显示哪些资源Overview (概览) : 展示检索资源的时间轴&#xff0c;多个垂直堆叠的栏意味着这些资源被同时…

2024杭州国际安防展览会:引领数字城市安全与智能未来

随着科技的不断进步&#xff0c;数字城市已经成为未来城市发展的重要趋势。作为数字城市建设的重要组成部分&#xff0c;安防技术的创新与应用对于保障城市安全、提高生活品质具有重要意义。为此&#xff0c;2024杭州国际安防展览会将于4月份在杭州国际博览中心隆重召开&#x…

储能新纪元:第十三届中国国际储能大会(CIES2023)深度洞察与未来趋势

随着全球能源结构的持续优化和可再生能源的迅猛发展&#xff0c;储能技术作为支撑能源转型的关键力量&#xff0c;日益受到世界各国的关注。 在这一背景下&#xff0c;2023年第十三届中国国际储能大会&#xff08;CIES2023&#xff09;的召开&#xff0c;无疑为行业内外人士提…

PDF中公式转word

效果&#xff1a;实现pdf中公式免编辑 step1: 截图CtrlAltA&#xff0c;复制 step2: SimpleTex - Snip & Get 网页或客户端均可&#xff0c;无次数限制&#xff0c;效果还不错。还支持手写、文字识别 单张图片&#xff1a;选 手写板 step3: 导出结果选择 注&#xff1a;…

网络协议与攻击模拟_12DNS协议及Windows部署DNS服务器

1、了解域名的结构 2、DNS查询过程 3、Windwos server部署DNS服务器 4、分析流量 实施DNS欺骗 再分析 一、DNS域名系统 1、DNS简介 DNS&#xff08;Domain Name system&#xff09;域名系统&#xff0c;作为将域名的IP地址的相互映射关系存放在一个分布式的数据库&#xff0c…

OBB头篇 | 原创自研 | YOLOv8 更换 SEResNeXtBottleneck 头 | 附详细结构图

左图:ResNet 的一个模块。右图:复杂度大致相同的 ResNeXt 模块,基数(cardinality)为32。图中的一层表示为(输入通道数,滤波器大小,输出通道数)。 1. 思路 ResNeXt是微软研究院在2017年发表的成果。它的设计灵感来自于经典的ResNet模型,但ResNeXt有个特别之处:它采用…

小米服务治理——客户端熔断器(Google SRE客户端熔断器)

目录 前言 一、什么是Google SRE熔断器 二、Google SRE 熔断器的工作流程&#xff1a; 三、客户端熔断器 (google SRE 熔断器) golang GRPC 实现 四、客户端熔断器 (google SRE 熔断器) golang GRPC单元测试 大家可以关注个人博客&#xff1a;xingxing – Web Developer …

【动态规划】【C++算法】1340. 跳跃游戏 V

作者推荐 【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数 本文涉及知识点 动态规划汇总 LeetCode1340跳跃游戏 V 给你一个整数数组 arr 和一个整数 d 。每一步你可以从下标 i 跳到&#xff1a; i x &#xff0c;其中 i x < arr.length 且 0 < x…

提及闭包函数,不得不说【python装饰器】

什么是装饰器 1. python装饰器是用于拓展原来函数功能的一种函数&#xff0c;目的是在不改变原函数的情况下&#xff0c;给函数增加功能。 2. 装饰器是通过闭包实现&#xff0c;所以讲装饰器首先得知道什么是闭包。 前言 什么是闭包 一、什么是闭包 1. 一个定义在函数内部的函…

[职场] 个人简历教育背景怎么填 #其他#笔记#媒体

个人简历教育背景怎么填 一个人的受教育程度很大部分决定了此人的专业素质&#xff0c;简历中的教育背景是HR衡量求职者的标准&#xff0c;因此教育背景部分在简历中比较靠前。 怎么写教育背景&#xff1f; 1、时间 首先&#xff0c;最重要的是你要注明好时间&#xff0c;时间都…

idea搭建spring5.3.x源码环境

1.写在前面的话 碰到了不少想阅读或者学习spring源码的同学&#xff0c;但是第一步搭建这个源码阅读环境就能难倒了一大批人。下面我就以spring5.3.x这个源码分支&#xff0c;来具体演示一下搭建过程。 2. 下载源码 下载源码这一步&#xff0c;说实话&#xff0c;由于某些原…

STM32控制DS18B20温度传感器获取温度

时间记录&#xff1a;2024/1/28 一、DS18B20温度传感器介绍 &#xff08;1&#xff09;测温范围-55℃~125℃&#xff0c;在-10℃到85℃范围内误差为0.4 &#xff08;2&#xff09;返回的温度数据为16位二进制数据 &#xff08;3&#xff09;STM32和DS18B20通信使用单总线协议…

算法模板 3.二分查找

二分查找 789. 数的范围 - AcWing题库 check函数&#xff08;lr&#xff08;这里要不要1&#xff09;&#xff09;>> 1 &#xff0c;要根据具体情况&#xff0c;如果是r mid的话lr就不用1&#xff0c;l mid的话就要1 #include <bits/stdc.h> using namespace s…

Android Retrofit添加header参数

前言 有些接口需要单独设置header参数 作为标记 如何灵活 或者统一设置请求header呢 注解Headers 顾名思义 Headers是指多个header 放在对象里 统一管理 //获取xxx Headers({"Content-Type: application/json","User-Agent: test"}) POST("xxxx&q…

小程序:类型三级分类

一、效果图片 二、代码 <template><view class"customPosition"><!-- header --><navBar :border"false" :hasBack"true" :title"titleName"></navBar><!-- 查询 --><view class"search…

JavaWeb之打包失败解决方案

情况描述&#xff1a; ---打包不成功 这时点击Maven中的蓝色小闪电&#xff1a; 小闪电的意思&#xff1a;是否跳过测试。点击选中就可以跳过&#xff0c;打包的时候就可以跳过测试代码。 再次打包后即可成功&#xff1a; 查看具体打包后的jar包&#xff1a; 打包后&#x…

openGaussdb5.0单点企业版部署_Centos7_x86

本文档环境&#xff1a;CentOS7.9 x86_64 4G1C40G python2.7.5 交互式初始化环境方式 介绍 openGauss是一款开源关系型数据库管理系统&#xff0c;采用木兰宽松许可证v2发行。openGauss内核深度融合华为在数据库领域多年的经验&#xff0c;结合企业级场景需求&#xff0c;持续…