51单片机--动态数码管(含源码、消隐问题)
利用51单片机的动态数码管模块实现数码管显示实验,包括静态数码管、动态数码管。74138译码器的讲解,相关电路的分析,代码的分享,以及消隐知识的学习,通过此节熟悉对51单片机的相关理解,以及对c语言的数组、函数模块化等知识的学习。
目录
实验介绍:利用51单片机的动态数码管模块实现数码管显示实验,包括静态数码管、动态数码管。74138译码器的讲解,相关电路的分析,代码的分享,以及消隐知识的学习,通过此节熟悉对51单片机的相关理解,以及对c语言的数组、函数模块化等知识的学习。
实验设备:普中51-实验板
实验目录:
1、任意位置显示数字
2、多位置显示多个数据
一、硬件部分
1.1 LED数码管
本实验涉及的硬件包括两部分,1是LED数码管,2是74HC138译码器。
LED数码管是一种简单、廉价的显示器,由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表示。通过控制8个段来控制数码管显示的数字,其段分布如下图所示:
动态数码管模块在开发板的位置如下图所示,采用两个四位一体的数码管构成。
1.2 74HC138译码器
74HC138是一种译码器,译码编码的逆过程,在编码时,每一种二进制代码,都赋予了特定的含义,即都表示了一个确定的信号或者对象。把代码状态的特定含义“翻译”出来的过程叫做译码,实现译码操作的电路称为译码器。
74138译码器是三端子输入,八个端口输出的译码器。将3位二进制译成8种输出状态。74HC138实现了用3根线选择8根线(8选1)的功能。74138模块在开发板机的位置如下图所示:
二、原理图
2.1动态数码管模块
下图为开发板中动态数码管模块电路图,我们可以从电路图中看出。动态数码管的上端分别为LED1-8,通过控制LED1-8的电平来控制某一位的数码管显示,称之为:位选;
在数码管的下方是每个LED的8个位a,b,c,d,e,f,g,dp。通过电路与 74HC245模块相连,通过控制74HC245模块的输出来控制某一数码管显示的数字,即a-dp的哪些段,称之为:段选;
位选:控制LED1-8,用于确定8个数码管的某一位;(如第二个数码管亮)。
段选:控制a,b,c,d,e,f,g,dp,用于确定某一个数码管显示的数字;(如显示的数字为6)。
在上述电路图中,数码管的段选输入口连接的是74HC245模块的输出口,此处我们简单介绍一下74HC245模块。74HC245 是一种三态输出、八路信号收发器,主要应用于大屏显示,以及其它的消费类电子产品中 增加驱动。简单来说,74HC245的作用就是用于功率的放大,从引脚的角度看,其输入P00-P07刚好对应的是晶体管的a,b,c,d,e,f,g,dp。
2.2 74HC138译码器模块
下图为开发板中 74HC138译码器模块电路图,我们可以从电路图中看出其输入端为P22-P24,输出端为LED1-LED8,为一种三通道输入、八通道输出译码器,通过P22-P24控制LED1-LED8,是一种低电平有效器件。即将3位二进制(P22-P24),译码成8种
输出状态,并且一共有8个
输出I/O,这8位输出的特点是:同时只有一位有效、低电平表示有效,表示选中,74HC138实现了用3根线选择8根线(8选1)的功能。
74HC138的管脚定义以及说明:
真值表是在逻辑中使用的一类数学表,用来确定一个表达式是否为真或有效。其中H代表高电平,L代表低电平,X代表随机电平(可高可低)。通过上述真值表可以确定P22-P24是如何控制LED1-LED8的。
2.3 单片机核心模块
下图为单片机的核心模块电路图,用到的引脚用红色框选,分别为74HC245的输入与74H138的输入。
三、代码分享
3.1 任意位置显示数字
例如:让第五个数码管亮,并且显示数字为3;
代码分享:
#include <REGX52.H>//包含51头文件
void main()//定义主函数
{
while(1)///定义循环,单片机只有靠代码执行,所以此处需要用到循环
{
P0=0x4f;//确定亮的数字
P2_2=1;//确定亮的位置
P2_3=1;
P2_4=0;
}
}
结果显示:
其中,确定数字的P0端不同数字对应的P0的值如下表:
其中,确定晶体管的位置(LED1-8)与P22-P24值如下表:
3.2 多位置显示多个数据
举例:数码管1-8的位置分别显示数字1-8;
按照上面的分析,此处的数码管只能在同一时刻,在某一个位置显示一种数字,那么如何显示出不同的数字呢?我们可以让代码不停的运行,第一个位置显示完第一个数字然后紧接着第二个位置显示第二个数字,依次再进行循环。
代码分享:
#include <REGX52.H>//包含51头文件
void SHUZI(unsigned int x,y)//定义调用函数,含有两个形参
{
switch(x)//确定第一个形参的值,即位选
{
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;
}
switch(y)//确定第二个形参的值,即段选
{
case 1: P0=0x06; break;
case 2: P0=0x5b; break;
case 3: P0=0x4f; break;
case 4: P0=0x66; break;
case 5: P0=0x6d; break;
case 6: P0=0x7d; break;
case 7: P0=0x07; break;
case 8: P0=0x7f; break;
}
}
void main()//定义主函数
{
int i;
while(1)//进行循环
{
for(i=1;i<9;i++)//形参和实参的值调用一次+1
{
SHUZI(i,i);//函数调用
}
}
}
此处,用到了C语言的函数调用的相关知识,如果有疑问请看我之前写的这篇博客,里面详细介绍了函数调用等相关C语言的知识;C语言---利用函数实现模块化程序设计。
C语言---利用函数实现模块化程序设计_King~30+的博客-CSDN博客C语言---利用函数实现模块化程序设计_King~30+的博客-CSDN博客C语言---利用函数实现模块化程序设计_King~30+的博客-CSDN博客
上述代码实现的功能就是依次在数码管的1-8位置显示数字1-8;其实验结果如下:
我们可以看见,数码管的位置上都进行了显示,但是隐隐约约在每个数码管的位置处都显示了好几个数字,不能够达到我们的要求,这便是数码管的消隐。
根据数码管上述代码的显示原理,显示的顺序是:位选->段选->位选->段选->位选->段选->一直重复下去,这样就会出现一个问题,当完成一个位选的时候(非首个),在紧接着段选之前的这段时间,此时的段选还是处于前一个操作的段选,这就会导致此处的LED显示上一个LED的状态,这也就是会产生阴影的原因。
解决消隐的方法:
1、延迟所要显示的状态(主函数中增加延迟函数)
在上述阴影状态中,错误的显示时间与正确的显示时间是相同的,这样就会出现极其严重的阴影,我们可以在主函数中增加延时函数让正确的时间多显示一会,这样阴影问题就会得到极大的改善。但是需要注意的是的延时的时间,如果延迟很短就还会有较严重的阴影,如果延迟很长,就会出现流水灯的现象,这种方法是治标不治本的。
2、在进行段选完成后,进行清零
在一次位选->段选->显示后,对段选进行清零,这样即使在下一个位选确定时,由于段选为0,此时也不显示,能够达到真正的消隐。
主函数增加延时:
void main()
{
int i;
while(1)
{
for(i=1;i<9;i++)
{
SHUZI(i,i);
Delay1ms(1) ;//延时函数,通过调节数字来确定延时的时间;
}
}
延时过短:消隐效果不明显
延时过长:出现流水灯现象;
数码管消隐流水灯
在段选和下一位选之间添加清零代码即可彻底消影。
#include <REGX52.H>//包含51头文件
void Delay1ms(unsigned int x) //@12.000MHz定义延时函数
{
unsigned char i, j;
while(x--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
void SHUZI(unsigned int x,y)//定义调用函数,两个形参,一个确定位选,一个确定段选
{
switch(x)//确定位选
{
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;
}
switch(y)//确定段选
{
case 1: P0=0x06; break;
case 2: P0=0x5b; break;
case 3: P0=0x4f; break;
case 4: P0=0x66; break;
case 5: P0=0x6d; break;
case 6: P0=0x7d; break;
case 7: P0=0x07; break;
case 8: P0=0x7f; break;
}
Delay1ms(1);//进行显示的时间
P0=0X00;//段选清零
}
}
void main()//定义主函数
{
int i;
while(1)//进行循环
{
for(i=1;i<9;i++)
{
SHUZI(i,i);//传参,位选段选的数字
}
}
}
结果如下:
总结:本节介绍了51单片机实现数码管显示(静态与动态),详细介绍了使用的各个模块的原理,作用,以及相关的电路分析,分享了相关的源码,解决了经常出现的一些问题,比如消隐等等;
大家在看完本片博客之后一定要进行自己动手的尝试,如果对有些操作不太明白,可以学习我之前的博客内容,学习都是循序渐进的。创作过程难免会有一些问题,欢迎大家进行讨论交流,
创作不易,还请大家多多点赞支持!!!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)