51 数码管

本文详细介绍了51数码管的工作原理,包括数码管的结构、引脚定义(共阴极和共阳极)、四位一体的优势、74HC138和74HC245在驱动中的作用,以及动态数码管显示的原理和使用方法。特别关注了STC89C52RC开发板上的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

51 数码管

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

STC89C52RC开发板上的数码管

在这里插入图片描述

数码管引脚定义

一位数码管

图源:B站:江协科技 视频截图

在这里插入图片描述

上图为共阴极连接,下图为共阳极连接(即连接3或8都可),控制高低电平的0和1即为段码

四位一体数码管

图源:B站:江协科技 视频截图

在这里插入图片描述

在同一时刻只能有一个数码管被使用,即使有多个,也显示相同数字(有利于减少利用的引脚,只引出12个就可以操作32个二极管)

动态数码管显示是利用视觉暂留和数码管显示的余晖,通过快速扫描来实现

*STC89C52RC开发板上的数码管示意图(图源:普中科技参考手册)

在这里插入图片描述

该数码管为共阴极数码管(COM为公共端)

上面的LED接的是138译码器的输出端


数码管模块前后及内部还有以下较为重要的部件

74HC138

可以通过3个IO口(ABC)控制8个端口,其中C为高位,A为低位

下面的G1等为使能端(G1需要高电平,G2需要低电平),根据图示,通电即工作

译码器工作原理:

将3为二进制数字转换成10进制,使对应的端口(0~7)为低电平

P24为高位,读数从P22开始读(P22为最低位)
图源:普中科技参考手册

在这里插入图片描述

STC89C52RC开发板上的74HC138

在这里插入图片描述

74HC245

由模块示意图可知,模块的开头接有74HC245芯片

74HC245芯片为双向数据缓冲器:用于数据缓冲(A1-B0,A1-B1,以此类推)

OE也相当于使能端,接地工作

图源:普中科技参考手册

在这里插入图片描述

STC89C52RC开发板上的74HC245

在这里插入图片描述

DIR控制数据传递的方向(用跳线帽控制方向,接高电平VCC为从左向右,低电平为从右到左)

目的:单片机输出的最大电流有限,高电平驱动能力弱(灯会很暗),低电平驱动能力强

即单片机输出的电平就相当于一个信号,实际驱动二极管的为芯片自己的电源

STC89C52RC开发板上的跳线帽

在这里插入图片描述

其中P07为高位(即端口高位对应数据高位),读数从P00开始读

限流电阻

两个四位一体的排阻(也可以是8个独立的电阻),防止电流过大

图源:普中科技参考手册

在这里插入图片描述

STC89C52RC开发板上的限流电阻

在这里插入图片描述

数码管的显示

基础显示

在阴极(P2)选中需要显示数据的数码管,在阳极(P0)输入需要显示的数据

由模块图可知,我们需要在COM端设置需要显示的数码管低电平,在74HC245端向需要显示的数码管上对应的发光二极管输入高电平

(虽然各个数码管同一位置的二极管共用阳极,但此时由于其它的数码管的COM端仍旧为高电平,所以不会亮起)

输入需要显示的数据即为根据数码管的各个引脚对应的部分“画”出需要显示的数据


例:在第4位数码管显示数据,需要给 LED5 低电平,即P24 = 1;P23 = 0;P22 = 0 (二进制100 = 十进制4,即对应LED5)

(这里的P24可以时P2_4或P24,具体要看头文件的定义)

显示数据为4,则需要使abcdef均亮,则需要使P0 = 0x3F (0011 1111)


#include<STC89C5xRC.H>

void main()
{
    P2_4 = 1;
    P2_3 = 0;
    //此时LED3、4亮起(引脚冲突)
    P2_2 = 0;
    //控制74HC138

    P0 = 0x3F;
    //控制74HC245
    //第四个数码管显示0

    while(1)
    {
        
    }
}
通过数组和函数改造基础代码

通过创建相应的数组和函数,我们可以以函数调用的方式快速改变数码管的显示

有关C语言的知识可见作者专栏

C语言学习记录_flashier的博客-优快云博客

下面这段代码为创建一个包含显示0~9的对应代码的数组以及一个含有控制数码管显示位置的switch语句的函数

向函数传入显示位置和显示数据,可方便地改变数码管的显示状态

#include<STC89C5xRC.H>

unsigned char NixieTable[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9对应的段码

void NixieTube_Display(unsigned char location, unsigned char num)
//分别传入显示位置、显示数字
    //位置为从左向右1~8
{
    switch(location)
    {
        case 1:
            //最左边的数码管对应LED8
            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[num];
}

void main()
{
    NixieTube_Display(8, 9);
    while(1)
    {
        
    }
}

动态数码管显示

数码管驱动方式:

单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间(缺点:一旦程序阻塞,没来得及扫描,会导致数码管闪烁或熄灭)

【单片机直接扫描还有另一种模式:通过外接带74HC595的模块,用三根数据线和两根电源线控制8个数码管,可以节省单片机IO口

(在开发板上的数码管需要3+8=11个IO口才能控制8个数码管)】

专用驱动芯片:单片机通过协议告诉芯片(TM1640)显示什么,芯片内部自带显存、扫描电路

(只要两根线就可以控制16个数码管显示任意数字)


数码管快速扫描的过程:位选(选择控制哪个数码管)->段选(控制显示内容)->位选 的循环

因为单片机运行速度过快,这样会造成上一位段选的数据会跑到下一次位选的位置,导致显示的数据错乱

解决方法:在下一次位选之前将上一次段选数据清零

#include<STC89C5xRC.H>

unsigned char NixieTable[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void NixieTube_Display(unsigned char location, unsigned char num)
{
    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[num];
    Delay(1);
    //让数码管稳定显示,否则亮度会变低
    //这里作者已将延时1ms的函数写入头文件,向函数传递的数字x即为延时x ms
    P0 = 0x00;
    //清零
}

void main()
{
    NixieTube_Display(8, 0);
    while(1)
    {
        NixieTube_Display(1, 1);
        //Delay(500);
        NixieTube_Display(2, 2);
        //Delay(500);
        NixieTube_Display(3, 3);
        //Delay(500);
        //让数码管同时显示多个数字实际上就是数码管在不断扫描,可以通过延时函数来体现
    }
}
<think>我们要解决的是51单片机数码管显示中的消影问题。在动态数码管显示中,由于数码管的段选(控制显示什么数字)和位选(控制哪个数码管亮)是分时复用的,如果不采取消影措施,可能会出现重影(也称为鬼影)现象。原因:当切换位选时,如果段选数据没有及时更新或清除,上一个位选对应的段选数据可能会在下一个位选上短暂显示,造成视觉上的重影。解决方法:1.在切换位选之前,关闭所有段选(即让所有段都不亮),然后再切换位选,再打开新的段选数据。2.或者,在切换位选后,延时一小段时间再送段选数据(但是这种方法可能会降低亮度,且消影效果可能不如第一种)。常用方法是在切换位选前关闭段选(即清空段选锁存器),然后再打开新的位选和段选。以下是一个示例代码(以51单片机为例,使用C语言):假设我们使用P0口作为段选,P2口的低2位作为位选控制(这里用两个锁存器控制,实际上也可以使用其他方式,比如直接控制IO口)。我们使用两个锁存器:一个锁存器控制段选(我们称之为段锁),一个锁存器控制位选(我们称之为位锁)。通过控制锁存器的使能端来更新数据。具体步骤:1.首先关闭当前显示的数码管(即把段选全部置为不亮),这里可以通过向段锁发送0xff(共阴数码管)或0x00(共阳数码管)来实现。注意:共阴数码管,0是亮,1是灭;共阳数码管则相反。因此,对于共阴数码管,发送0xff可以让所有段都不亮。2.然后更新位选,选择下一个要显示的数码管。3.再更新段选数据,显示对应的数字。4.这样在切换时就不会有重影了。代码示例(假设使用共阴数码管):</think> ### 51数码管消影解决方案 在51单片机控制数码管时,消影(消除重影)是关键问题,主要原因是数码管动态扫描时,段选和位选信号切换不同步导致视觉残留。以下是完整的解决方案: ```c #include <reg52.h> // 定义段选和位选端口 #define SEG_PORT P0 // 段选数据端口 sbit LATCH_SEG = P2^0; // 段选锁存器 sbit LATCH_DIG = P2^1; // 位选锁存器 // 共阴数码管0-9段码表 unsigned char code seg_table[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, // 0-4 0x6D, 0x7D, 0x07, 0x7F, 0x6F // 5-9 }; // 需要显示的4位数 unsigned char display_num[] = {1, 2, 3, 4}; void delay(unsigned int ms) { unsigned int i, j; for(i=0; i<ms; i++) for(j=0; j<120; j++); } void display() { unsigned char i; for(i=0; i<4; i++) { // 1. 清除段选(关键消影步骤) SEG_PORT = 0x00; // 关闭所有段选 LATCH_SEG = 1; // 锁存段选数据 LATCH_SEG = 0; // 2. 切换位选 LATCH_DIG = 0; // 关闭位选锁存 SEG_PORT = 1 << i; // 设置当前位选 LATCH_DIG = 1; // 锁存位选数据 LATCH_DIG = 0; // 3. 更新段选数据 SEG_PORT = seg_table[display_num[i]]; // 送段码 LATCH_SEG = 1; // 锁存段选数据 LATCH_SEG = 0; delay(5); // 保持显示 } } void main() { while(1) { display(); // 循环显示 } } ``` ### 代码解释: 1. **核心消影原理**: - 先关闭所有段选(清空显示数据) - 再切换位选(选择要显示的数码管) - 最后更新段选数据(设置显示内容) - 这个操作序列确保切换时无信号冲突 2. **端口定义**: - `SEG_PORT`:段选数据端口(控制显示形状) - `LATCH_SEG`:段选锁存触发信号 - `LATCH_DIG`:位选锁存触发信号 3. **显示流程**: - **步骤1**:清除段选寄存器,避免残留显示 - **步骤2**:更新位选信号,选择下一个数码管 - **步骤3**:更新段选数据,显示具体数字 - 每个数码管显示5ms,利用视觉暂留效应形成稳定显示 4. **硬件连接**: - 建议使用74HC595等锁存器芯片 - 段选和位选信号都需要锁存器控制 - 在每个数码管的COM端串联300Ω电阻限流 ### 优化建议: 1. 增加消隐延时(清除段选后延迟100μs再切换位选) 2. 采用定时器中断刷新数码管,避免`delay`占用CPU 3. 对位选信号取反(当使用PNP三极管驱动时) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值