4.单片机之静态数码管和动态数码管

👿1.数码管的介绍

数码管相比较之前的按键和LED灯的内容稍微复杂一些,操作更加难一点♦

数码管位置:在单片机的最↖角的地方、八个型号的显示器件♦还有138译码器和右边的74C595存储器都是属于数码管操作这些的东西♦

数码管英文:Nixie tube♦

LED数码管:数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成"8"字器件♦

应用:数码管的价格由于相对便宜,在电器特别是家电领域应用极为广泛,空调、热水器、冰箱等等。绝大多数热水器用的都是数码管,其他家电也用液晶屏与荧光屏♦

💉2.数码管的分类

数码管 共阳数码管 共阴数码管

数码管其实就是8个段的发光二极管,只点亮其中的几个段即可显示出数字或字母用来表达信息♦

共阳数码管:把8段LED的正极并在一起作为公共端连接在5V上(共阳极),然后8个LED通过单片机的8个IO端口输出高低电平使其决定点亮哪几个段♦

八段LED数码管

分为共阳极及共阴极,共阳极的七段数码管的正极(或阳极)为八个发光二极管的共有正极。其他节点为独立发光二极管的负极(或阴极)♦

使用者只需把正极接电,不同的负极接地就能控制七段数码管显示不同的数字,共阴极的七段数码管与共阳极的只是接驳方法相反而已,同样根据上面所说的LED数码管分类方法,我们可以知道还有下面几种较常见的类型♦

九段LED数码管

相较七段LED数码管,该类更多用在数码手表和传呼机上♦

按显示位数分类

按能显示多少个“8”可分为1位、2位、3位、4位和多位led数码管

按发光二极管单元连接方式分类

按发光二极管单元连接方式分为共阳极数码管和共阴极数码管,共阳极数码管是指将所有发光二极管(LED)的阳极接到一起形成公共阳极(COM)的数码管。共阳极数码管在应用时,将公共阳极COM接到+5V

👹3.数码管的引脚定义

👻3.1一位一体类型

这种①位的数码管,它就是由⑧个LED灯组成的♦

那么这⑧个LED灯是怎么去连接的呢?在上述图片的右边当中可以看到。右边其实就是LED灯的连接方式,总共有两种连接方式!在上述图片当中它们的⑧个LED灯阴极都连接到了一个端口上,这种方式就叫做共阴极连接!下面图中它们⑧个LED灯阳极都连接到了一个端口上,这种方式就叫做共阳极连接!

那我们在看到这图上的左下角还定义了这个段的一个名称。首先它最上面的LED数字都起好了名字了分别是:A、B、C、D、E、F、G、DP💨这个断码加起来就是⑧个,正好和我们的①字节 = ⑧位 刚好相互对应的♦

还有一个图是引脚的定义!在③号引脚上连接的是正极,在⑧号引脚上连接的是负极。 引脚的定义图是按照"就近原则"来的♦

那我们要在数码管上显示数字"⑥"那怎么办呢?很简单我们把段码:A、C、D、E、F、G、都点亮即可,然后让其它的全部熄灭!那么它显示的就会是"⑥"。首先我们点亮,我们肯定要先把这个共阴极的公共端需要接地,接地那么就是给我们这个数据"零"或者是低电平,那么它的这个公共端阴极接到了这个的负极上。那么首先就达到了第一个条件了,它在共阴极上负极接上负极当我们负极接好之后,这个就叫做位选端,我们要把它选中它才能够亮,如果有多个点亮的话那么就控制它多个位选端。那么如果是共阳极的话那么我们是公共端是VCC,断码就是低电平"0"才会点亮(这个数据就是操作我们共阳极的数码管显示)♦

💩3-2四体一位

这种就是④位的数码管,它就是由④*⑧个LED灯组成的,在开发板上也是④位一体的。在单片机上总共有两个刚好是⑧个数码管♦

那么这个④位一体的数码管是如何连接的?首先它也是具有一个引脚的序号。如上图所示在↖角,总共有12个引脚。右边也是有②种的连接方式,在上面是共阴极连接,下面是共阳极连接♦

那我们对比下①位的数码管,就是多分出③个,它们的公共端是单独分出来的。然后,它们的断码就是全部的连接在了一起(A段、B段、.....DP段)♦

💥那么我们想到第三位数码管显示数字①的话,那么我们这么样才可以实现呢?首先,我们在位选(公共端)当中给第三位数码管给上"0"低电平,再给①、②、④上的位选给上"1"高电平,因为是共阴极。所以给低电平就可以让 位选 点亮。那么这就是只有第三个才会点亮,亮的前提是什么呢?位选端接上相应的数据,在'B'、'C'中给上数据'1',其余的全部给上'0'♦

😈4.数码管原理图

数码管和138译码器都是用来控制数码管显示的♦

COM就是公共端,这个数码管的就是共阴极的数码管。首先我们要点亮的话我们就要把它的公共端给选中。如果点亮第三个数码管的话,那么就把这第三个数码管选中"0",其它的公共端都选中"1"。 那么如果想要给数码管数据的话,那么就给数码管下面的段码给"1",如果想让第三位数字①的话,就把 B、C给上1,其它的都给上"0"♦

那么这里接上的网络编号(LED1~LED8)都是接到138译码器上的输出端 ,那么138译码器是什么工作原理呢?在这里解释一下:我们现在的目的是使得它的输出端输出为"0",剩下的全部输出"1"。那么这个138译码器正好可以实现这一个功能,并且还可以把③(P22、P23、P24)个端口变成⑧个端口来控制的!左边的 A、B、C、是输入端(正极)右边这个Y0~Y7是输出端(负极),这个是在数码管原理图上面的话是 💨 然后这个芯片需要接电源VCC上面的就是,下面就是它的电源负极GND。↙脚的③个引脚叫做它的使能端:相当于一种开关,如果使能电平有效的话,它就是可以进行工作的,如果无效的话它就不会进行工作♦

138译码器左上角的③个引脚上(P22、P23、P24),C是高位、B在中间、A是低位。按照顺序也就是 — C B A。从而我们这个138译码器从而也被称作是"③⑧线",好接下来就是怎么样去使用:其实这里的作用是让数码管的哪一位可以进行显示❗❗❗❗如果假设(P24、P23、P22) C B A ,把高低位进行排序之后,二进制转换为十进制数,对应着输出端(Y0~Y7),那么假设C B A:0 0 0 = Y0,从而:LED1是可以被允许显示的,因为这里"0"是输出端(低电平)(共阴极)才能让公共端LED1数码管允许显示,其它的7个都是不被允许的!如果是:0 0 1,那么转换成十进制数字就是:Y1 对应着 LED2,那么这里就是Y1是有效的值,Y1输出给上"0"(低电平)♦

总结:下来就是我们只要给上CBA的数据,然后用二进制转换成十进制的数据。对应着Y的引脚,然后再对应LED的引脚上,对应到了哪个LED给上输出端"0",那么这个LED就是有效位的数码管了♦

🌷5. 74HC245

74HC245这个芯片有什么作用呢?这个芯片被称之为双向数据缓冲器,这个芯片的作用,用来进行数据缓冲(提高驱动能力)的。那么缓冲这个是什么意思?

假设我们给上二进制,就从A0到达B0这是连接的关系,DIR(direction)如果接的是高电平(1)那么就能把左边的数据接到我们右边的数据上。电容CC2(100nf)在这里的作用是:芯片的供电更加稳定叫做电源滤波,然后电阻的哪些东西是④位一体的排阻,电阻的阻值是100R(Ω)作用:同样跟LED灯是一样的起到限流的作用,防止电流过大

🍆6.总结

看了前面的这些原理,那么对于在一个数码管上面显示数字来总结就是

1.在138译码器上控制③个口(P24、P23、P22)

2.看你(LED1~LED8)哪一位输出"0"低电平选中

比如说 C B A = 0 1 1 = 3,也就是=Y3 = LED4,LED4 就是有效的,允许显示数码管的,那么其它的数码管是不能被允许显示的、不是有效的。—— 位选

那么选中之后,就是给P0口段码的数据:假设给上数据,经过缓冲(74HC245)送到公共端的段码端。那么,送到段码端就会显示数码管相对应的数字!注意:P0口给上数据是从高位到低位给上段码端的(就是从P_7口开始往上面读数)—— 段选

就相当于两步骤:1、选中P2(进行位选在哪一个led上面亮) 2、给段码数据P0(进行段选在那个亮的led上面显示怎么样的数字)

🍓7.C语言数组

C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量♦

数组的声明并不是声明一个个的变量而是一个集合♦

🍻8.C语言子函数

返回类型:一个函数可以返回一个值。返回类型 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,返回类型 是关键字 void

函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数名称

参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数

函数主体:函数主体包含一组定义函数执行任务的语句

😋9.代码展示

9.1写一个代码在第三位上显示6这个数字

从那个原理图上可以看出来要从左到右边实际上是led6所以有代码

#include <REGX52.H>
 
void main()
{
    //显示数码管的位置
    P2_4=1;
    P2_3=0;
    P2_2=1;
    while(1)
    {
        //显示数码管的数字
        P0=0x7D;//01111102,从P0_7往上读数
    }
}

注意:LED会亮的原因是因为引脚冲突这个不需要去管它。

9.2写一个代码实现静态数码管显示
#include <REGX52.H>
//                          0    1    2    3    4    5    6    7    8    9
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
 
//Location:数码管的位置;    Number:显示数码管的数字【高电平点亮段码】    
void Nixie(unsigned char Location,Number)
{
    switch(Location)          //位码端输出
    {
        //开发板上是逆序为1
        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]; //P0接收数码管中的数字
}
void main()
{
    Nixie(2,2);
    while(1)
    {
        
    }
}

注意:静态数码管只能显示一个数字,不需要做到消影,那么当多个数字需要显示在数码管上时候,那么就是动态数码管了

9.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,消影
}

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

那么在这里解释下数码管的消影就是比方说:

当我们要显示数码管的时候首先要:位选 段选、还要显示的话就还要 位选、段选,循环。

那么这样就会出现问题:首先是选择"位选端"给上低电平,然后是段选给上数据,然后给上下一位位选的数据。但是:由于我们单片机的速度是很快的,在段选到下一个位选之间就会出现问题。我们选中下一位这个时刻很短的时间内,上一个数据就会串到下一个数据。因为它们是挨着一起的,我在选中下一位之后 上一位的数据自然是会直接过来的。这样就会显示出数据的串位的问题了

那么我们应该怎么避免这个问题?那我们就需要在上一个段选端给清零这样即使到下一位它也不会对上一位产生影响!因为以及清零了。所以在子函数上需要优化下,显示玩之后我们首先要延迟1ms这个是为了能让程序更加稳定显示 并且进行清零,就可以达到消影的目的

9.3.1数码管的两种驱动方式

数码管静态显示驱动

静态驱动也称直流驱动。静态驱动是指每个数码管的每一个段码都由一个单片机的 I/O端口进行驱动,或者使用如BCD码二-十进制译码器译码进行驱动。静态驱动的优点是编程简单,显示亮度高,缺点是占用I/O端口多,如驱动5个数码管静态显示则需要5×8=40根I/O端口来驱动,要知道一个89S51单片机可用的I/O端口才32个呢:),实际应用时必须增加译码驱动器进行驱动,增加了硬件电路的复杂性。

数码管动态显示驱动

数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示过程中,每位数码管的点亮时间为 1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的示例代码,用于演示c51单片机如何实现静态数码管和蜂鸣器同时运行: ``` #include <reg52.h> // 数码管显示数据和对应引脚 unsigned char code DIGIT[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; sbit D1 = P1^0; sbit D2 = P1^1; sbit D3 = P1^2; sbit D4 = P1^3; // 蜂鸣器引脚 sbit BUZZER = P2^0; // 定时器中断服务程序 void Timer0_ISR() interrupt 1 { static unsigned char i = 0; static unsigned char count = 0; TH0 = 0xff; TL0 = 0x9c; // 定时器计数值调整,可根据具体硬件调整 count++; if (count == 10) { // 控制蜂鸣器响声的时间,可根据需求调整 BUZZER = 0; } else if (count == 20) { BUZZER = 1; count = 0; } switch (i) { // 循环显示数码管的每一位 case 0: D1 = 0; D2 = 1; D3 = 1; D4 = 1; P0 = DIGIT[1]; break; case 1: D1 = 1; D2 = 0; D3 = 1; D4 = 1; P0 = DIGIT[2]; break; case 2: D1 = 1; D2 = 1; D3 = 0; D4 = 1; P0 = DIGIT[3]; break; case 3: D1 = 1; D2 = 1; D3 = 1; D4 = 0; P0 = DIGIT[4]; break; default: break; } i++; if (i == 4) { i = 0; } } void main() { TMOD = 0x01; // 定时器模式设置为定时/计数模式 TH0 = 0xff; TL0 = 0x9c; // 定时器计数值调整,可根据具体硬件调整 EA = 1; // 开启总中断 ET0 = 1; // 开启定时器中断 TR0 = 1; // 开启定时器 while (1); // 主程序循环 } ``` 需要注意的是,这只是一个简单的示例代码,具体的实现方式和代码结构可能会因为硬件和需求的不同而有所变化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值