两个74HC595驱动共阳4位段选数码管

74HC595-串入/串并出带锁存的移位寄存器,实在是灰常magic,用它来驱动8段数码管太方便了!除了静态驱动可无限串联的一位数码管,它还能用来动态驱动4位段选数码管,而且由于串入/串并出和锁存特性,动态驱动也能够不闪烁显示并无限串联。

原理图
(两个74HC595分别做段选和段显,数码管为0.56寸4位共阳SR410561N)

PCB板


需不需要使用三极管?
74HC595的IO输出电流推荐为20mA,而数码管的限流电阻为1K欧姆时大概工作电流为10mA左右,因此使用74HC595的IO作为段选,提供数码管的阳极电流,不用再增加三极管了。74HC595的总电流不能超过70mA,所以这里只使用它驱动4个段选信号。 (好吧,由于动态显示是扫描的,每一时刻只点亮一个,所以驱动8个段选信号是没有问题的,74HC595的资源就全部利用了)

程序设计
动态驱动4位段选数码管的原理是,每个小间隔,使能一个段选信号,点亮它对应的段显。循环使能这4个段选信号,由于人的视觉停留,看起来就好像是同时点亮的。所以程序设计的时候,就需要每个小间隔对它操作一次,在主函数或者定时器中断里面都可以。

调试这个小模块的时候,我遇到了两个问题: 第一,显示有闪烁;第二,没用到的段会轻微点亮。

第一个问题解决的很快,闪烁是因为显示速度太慢,提高显示速度就可以;第二个问题是因为我的初版程序里面,每移位8bit就锁存一次,因此段选信号会在瞬间作为段显信号,所以明明不该亮起来的段会看起来微微亮,解决方法是段选和段显信号都发送完成之后再锁存。


/*************************************************
驱动4位段选数码管的方法:
HC595_single_4BIT的功能是,将段显信号byte发送,然后使能第byte_position个的段选信号;
发送完毕之后更新锁存(而不是每个for分别更新),实际显示的效果非常漂亮;
当多个这样的模块串联时,会发现它们都会显示“3210”;
get_square的功能是,计算2的3-byte_position次幂,并存放在byte_position_t中。
**************************************************/

void HC595_single_4BIT(int8_t byte, int8_t byte_position)
{
    int8_t i = 0, j = 0;
    uint32_t byte_position_t = 0;
    get_square(2, 3 - byte_position, &byte_position_t);

    for (i = 0; i < 8; i++) {
        if (byte & 0x80)
            HC595_DAT_H_4BIT();
        else
            HC595_DAT_L_4BIT();
        HC595_SCK_L_4BIT();
        HC595_SCK_H_4BIT();
        byte = byte << 1;
    }
    for (i = 0; i < 8; i++) {
        if (byte_position_t & 0x80)
            HC595_DAT_H_4BIT();
        else
            HC595_DAT_L_4BIT();
        HC595_SCK_L_4BIT();
        HC595_SCK_H_4BIT();
        byte_position_t = byte_position_t << 1;
    }
    HC595_RCK_L_4BIT();
    HC595_RCK_H_4BIT();
}

int main (void)
{
    /*
    functions();
    */   

    while (1) {
        HC595_single_4BIT(LGBH38_HC595_DEC_4BIT[0], 0);Delay100Us_xt2_8MHz(1);
        HC595_single_4BIT(LGBH38_HC595_DEC_4BIT[1], 1);Delay100Us_xt2_8MHz(1);
        HC595_single_4BIT(LGBH38_HC595_DEC_4BIT[2], 2);Delay100Us_xt2_8MHz(1);
        HC595_single_4BIT(LGBH38_HC595_DEC_4BIT[3], 3);Delay100Us_xt2_8MHz(1);
    }   
    return 0;
}

/*************************************************
驱动多个4位段选数码管的方法一:
由于74HC595的串入/串并出特性,这个模块可以无限串联使用,但是使用上面的程序,没有办法单独点亮后级,因为后级的数据始终是前级推出来的,而前级始终处在4位段选的循环中。
所以程序需要做一些修改,使得在每个小间隔里面,能够对后级单独操作。
基本原理是,假如有len个模块串联使用,先将要显示的len_position之前的熄灭,然后发送byte和byte_position,再将len_position之后的熄灭;完成之后更新锁存器。
虽然它可以单独对任何段选和段显进行操作,但是随着串联个数的增加,亮度也会降低。
**************************************************/

void HC595_multi_4BIT(int8_t len, int8_t len_position, int8_t byte, int8_t byte_position)
{
    int8_t i = 0, j = 0;
    uint32_t byte_position_t = 0;
    get_square(2, 3 - byte_position, &byte_position_t);

    for (j = 0; j < len - len_position - 1; j++) {
        HC595_DAT_H_4BIT();
        for (i = 0; i < 8; i++) {
            HC595_SCK_L_4BIT();
            HC595_SCK_H_4BIT();
        }
        HC595_DAT_L_4BIT();
        for (i = 0; i < 8; i++) {
            HC595_SCK_L_4BIT();
            HC595_SCK_H_4BIT();
        }
    }

    for (i = 0; i < 8; i++) {
        if (byte & 0x80)
            HC595_DAT_H_4BIT();
        else
            HC595_DAT_L_4BIT();
        HC595_SCK_L_4BIT();
        HC595_SCK_H_4BIT();
        byte = byte << 1;
    }
    for (i = 0; i < 8; i++) {
        if (byte_position_t & 0x80)
            HC595_DAT_H_4BIT();
        else
            HC595_DAT_L_4BIT();
        HC595_SCK_L_4BIT();
        HC595_SCK_H_4BIT();
        byte_position_t = byte_position_t << 1;
    }

    for (j = 0; j < len_position; j++) {
        HC595_DAT_H_4BIT();
        for (i = 0; i < 8; i++) {
            HC595_SCK_L_4BIT();
            HC595_SCK_H_4BIT();
        }
        HC595_DAT_L_4BIT();
        for (i = 0; i < 8; i++) {
            HC595_SCK_L_4BIT();
            HC595_SCK_H_4BIT();
        }
    }

    HC595_RCK_L_4BIT();
    HC595_RCK_H_4BIT();
}

int main (void)
{
    /*
    functions();
    */

    while (1) { /*****会显示 76543210 *********/
        HC595_multi_4BIT(2, 0, LGBH38_HC595_DEC_4BIT[0], 0);Delay100Us_xt2_8MHz(1);
        HC595_multi_4BIT(2, 0, LGBH38_HC595_DEC_4BIT[1], 1);Delay100Us_xt2_8MHz(1);
        HC595_multi_4BIT(2, 0, LGBH38_HC595_DEC_4BIT[2], 2);Delay100Us_xt2_8MHz(1);
        HC595_multi_4BIT(2, 0, LGBH38_HC595_DEC_4BIT[3], 3);Delay100Us_xt2_8MHz(1);

        HC595_multi_4BIT(2, 1, LGBH38_HC595_DEC_4BIT[4], 0);Delay100Us_xt2_8MHz(1);
        HC595_multi_4BIT(2, 1, LGBH38_HC595_DEC_4BIT[5], 1);Delay100Us_xt2_8MHz(1);
        HC595_multi_4BIT(2, 1, LGBH38_HC595_DEC_4BIT[6], 2);Delay100Us_xt2_8MHz(1);
        HC595_multi_4BIT(2, 1, LGBH38_HC595_DEC_4BIT[7], 3);Delay100Us_xt2_8MHz(1);
    }   
    return 0;
}

/*************************************************
驱动多个4位段选数码管的方法二:
动态驱动,每个小间隔只能使能其中一个段选,上面的程序是假如有12个段选,就在12个小间隔里面循环使能,优点是可以单独操作任何一段,缺点是亮度会降低。
其实可以仍然使用4个小间隔,在每个小间隔里面,发送bytex段显信号,使能所有串联模块的第byte_position个段选。
因为后级串联的模块个数不确定,所以使用变参函数会方便一些。
**************************************************/

void HC595_multi_dis_4BIT(int8_t len, int8_t byte_position, int8_t byte_h, ...)
{
    int8_t i = 0, j = 0, bytex = 0;
    uint32_t byte_position_t = 0, byte_position_save = 0;

    get_square(2, 3 - byte_position, &byte_position_save);
    char *p = (char *)&byte_h;
   
    for (j = 0; j < len; j++) {
        bytex = *((int *)p);
        p += sizeof(int);
        for (i = 0; i < 8; i++) {
            if (bytex & 0x80)
                HC595_DAT_H_4BIT();
            else
                HC595_DAT_L_4BIT();
            HC595_SCK_L_4BIT();
            HC595_SCK_H_4BIT();
            bytex = bytex << 1;
        }
        byte_position_t = byte_position_save;
        for (i = 0; i < 8; i++) {
            if (byte_position_t & 0x80)
                HC595_DAT_H_4BIT();
            else
                HC595_DAT_L_4BIT();
            HC595_SCK_L_4BIT();
            HC595_SCK_H_4BIT();
            byte_position_t = byte_position_t << 1;
        }
    }
    HC595_RCK_L_4BIT();
    HC595_RCK_H_4BIT();   
}
int main (void)
{
     /*
    functions();
    */

    while (1) { /******会显示 222211110000 ***********/

        HC595_multi_dis_4BIT(3, 0, LGBH38_HC595_DEC_4BIT[2], LGBH38_HC595_DEC_4BIT[1],
                LGBH38_HC595_DEC_4BIT[0]);
        DelayMs_xt2_8MHz(1);

        HC595_multi_dis_4BIT(3, 1, LGBH38_HC595_DEC_4BIT[2], LGBH38_HC595_DEC_4BIT[1],
                LGBH38_HC595_DEC_4BIT[0]);
        DelayMs_xt2_8MHz(1);

        HC595_multi_dis_4BIT(3, 2, LGBH38_HC595_DEC_4BIT[2], LGBH38_HC595_DEC_4BIT[1],
                LGBH38_HC595_DEC_4BIT[0]);
        DelayMs_xt2_8MHz(1);

        HC595_multi_dis_4BIT(3, 3, LGBH38_HC595_DEC_4BIT[2], LGBH38_HC595_DEC_4BIT[1],
                LGBH38_HC595_DEC_4BIT[0]);
        DelayMs_xt2_8MHz(1);
    }   
    return 0;
}

最后,趁着某xx的单反相机还在这里,留一张渣图:

  • 2
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用74HC595可以实现对6位共阳数码管的段和位控制,具体实现步骤如下: 1. 确定数码管的位和段引脚,以及74HC595的输出引脚。将6个共阳数码管的8个段引脚连接到一个74HC595芯片的输出引脚上,将6个共阳数码管的位引脚连接到另一个74HC595芯片的输出引脚上。 2. 配置74HC595芯片的控制引脚,包括SER(串行数据输入)、SRCLK(移位寄存器时钟)、RCLK(锁存器时钟)和OE(输出使能)等引脚。其中,SER引脚连接到单片机的输出引脚,SRCLK和RCLK引脚连接到单片机的GPIO引脚,OE引脚连接到电路板上的电源。 3. 将需要显示的数字或字符转换为对应的段和位码,然后将数据依次写入到74HC595芯片的移位寄存器中。这里需要注意的是,需要先写入位码,再写入段码,以保证数码管能正确显示。 4. 通过向74HC595芯片的锁存器时钟RCLK引脚写入脉冲,保证寄存器中的数据被锁存。 5. 将每个74HC595芯片的输出引脚连接到对应的数码管的位和段引脚上,以控制数码管的显示。 需要注意的是,由于74HC595芯片只能控制8位输出,因此需要至少2个74HC595芯片才能控制一个共阳数码管。而对于6个共阳数码管,需要至少12个74HC595芯片才能完成控制。此外,还需要根据实际情况进行电路设计和程序编写,以保证电路的正确性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值