找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3055|回复: 52
收起左侧

用5个74hc595芯片级联,控制27位数码管,数码管显示闪烁问题

  [复制链接]
回帖奖励 10 黑币 回复本帖可获得 10 黑币奖励! 每人限 1 次(中奖概率 50%)
ID:298743 发表于 2024-4-12 15:49 | 显示全部楼层 |阅读模式
用了5个74hc595芯片级联,控制27位数码管,数码管闪烁,怀疑是写入74HC595数据的时间太长导致的,现在很怕是本来硬件设计的缺陷。
  我的程序大概是这样的,先用定时器0来计时,再用定时器1来刷新数码管的刷新,因为用到5块595芯片,所以写了一个函数来写入595的数据,高32位是位选,低八位是段选。
  数码管显示单片机程序:
#include "display.h"unsigned char code leddata[]={
        0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40
};/*数码管显示数字0,1,2,3,4,5,6,7,8,9,-*/

unsigned char LEDBuf[] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};//数据显示缓冲区
unsigned long code PLACE_CODE[] =
{0xFFFFFFFE,0xFFFFFFFD,0xFFFFFFFB,0xFFFFFFF7,0xFFFFFFEF,0xFFFFFFDF,0xFFFFFFBF,0xFFFFFF7F,0xFFFFFEFF,0xFFFFFDFF,0xFFFFFBFF,0xFFFFF7FF,0xFFFFEFFF,0xFFFFDFFF,0xFFFFBFFF,0xFFFF7FFF,0xFFFEFFFF,0xFFFDFFFF,0xFFFBFFFF,0xFFF7FFFF,0xFFEFFFFF,0xFFDFFFFF,0xFFBFFFFF,0xFF7FFFFF,0xFEFFFFFF,0xFDFFFFFF,0xFBFFFFFF}
;//  1           2         3           4          5          6           7         8          9          10         11         12         13         14         15         16          17          18         19        20          21         22         23        24           25         26       27  位选信号1-27位数码管
unsigned char digdot0 = 0,digdot1 = 0,digdot2 = 0,digdot3 = 0;//小数点控制变量
unsigned char digdot4 = 0,digdot5 = 0,digdot6 = 0,digdot7 = 0;

void Display()
{
        static unsigned char i = 0;//静态变量,只会赋值一次
        unsigned char temp;


        switch(i) //逐位输入数据
        {
        case 0:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[0]];
                if(digdot0 == 1)
                {
                        temp = leddata[LEDBuf[0]] | 0x80;        //控制小数点闪烁
                }
                led_hc595_drive(PLACE_CODE[0],temp);//高位字节是位选 低位字节是断码
                                led_hc595_off(0x00);

                i++;        
                break;
        case 1:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[1]];
                if(digdot1 == 1)
                {
                        temp = leddata[LEDBuf[1]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[1],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 2:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[2]];
                if(digdot2 == 1)
                {
                        temp = leddata[LEDBuf[2]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[2],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 3:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[3]];
                if(digdot3 == 1)
                {
                        temp = leddata[LEDBuf[3]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[3],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 4:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[4]];
                if(digdot4 == 1)
                {
                        temp = leddata[LEDBuf[4]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[4],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 5:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[5]];
                if(digdot5 == 1)
                {
                        temp = leddata[LEDBuf[5]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[5],temp);//高位字节是位选 低位字节是断码   
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 6:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[6]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[6]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[6],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 7:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[7]];
                if(digdot7 == 1)
                {
                        temp = leddata[LEDBuf[7]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[7],temp);//高位字节是位选 低位字节是断码  
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 8:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[8]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[8]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[8],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 9:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[9]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[9]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[9],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 10:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[10]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[10]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[10],temp);//高位字节是位选 低位字节是断码  
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 11:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[11]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[11]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[11],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 12:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[12]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[12]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[12],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 13:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[13]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[13]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[13],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试     
                i++;
                break;
        case 14:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[14]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[14]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[14],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 15:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[15]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[15]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[15],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 16:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[16]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[16]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[16],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 17:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[17]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[17]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[17],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 18:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[18]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[18]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[18],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 19:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[19]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[19]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[19],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 20:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[20]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[20]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[20],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 21:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[21]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[21]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[21],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 22:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[22]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[22]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[22],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 23:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[23]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[23]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[23],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试   
                i++;
                break;
        case 24:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[24]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[24]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[24],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 25:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[25]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[25]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[25],temp);//高位字节是位选 低位字节是断码
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i++;
                break;
        case 26:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[26]];
                if(digdot6 == 1)
                {
                        temp = leddata[LEDBuf[26]] | 0x80;
                }
                led_hc595_drive(PLACE_CODE[26],temp);//高位字节是位选 低位字节是断码  
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                i=0;
                break;



                default:break;
        }
        
}

5块595级联写入程序:
  #include "hc595.h"
#include "reg51.h"

void hc_595_init()
{
        //HC595_OE = 1;
        HC595_SH_CP = 0;
        HC595_ST_CP = 0;
        HC595_DS = 0;
        //HC595_OE = 0;
}






void led_hc595_drive(unsigned long datH,unsigned char datL)
{
        unsigned char i;
        unsigned long temp;
        unsigned char temp2;
        temp = datH;
        for(i = 0;i<32;i++)
        {
                //第一步准备数据,放到数据IO上
                if(temp >= 0x80000000)   //大概是比较这部分错了
                {
                        HC595_DS = 1;
                }
                else
                {
                        HC595_DS = 0;
                }
                HC595_SH_CP = 0;//上升沿 移位寄存器的数据移到存储寄存器
                HC595_SH_CP = 1;
                temp  <<=1;
        }
        temp2 = datL;
        for(i = 0;i<8;i++)
        {
                //第一步准备数据,放到数据IO上
                if(temp2 >= 0x80)
                {
                        HC595_DS = 1;
                }
                else
                {
                        HC595_DS = 0;
                }
                HC595_SH_CP = 0;//上升沿 移位寄存器的数据移到存储寄存器
                HC595_SH_CP = 1;
                temp2  <<=1;
        }
        HC595_ST_CP = 0;//上升沿 移位寄存器的数据移到存储寄存器
        HC595_ST_CP = 1;

        HC595_SH_CP = 0;//拉低,提高抗干扰
        HC595_ST_CP = 0;
        HC595_DS = 0;

}
void led_hc595_off(unsigned char dat1)
{
        unsigned char temp3;
        unsigned char i;
        temp3 = dat1;
        for(i = 0;i<8;i++)
        {
                //第一步准备数据,放到数据IO上
                if(temp3 >= 0x80)
                {
                        HC595_DS = 1;
                }
                else
                {
                        HC595_DS = 0;
                }
                HC595_SH_CP = 0;//上升沿 移位寄存器的数据移到存储寄存器
                HC595_SH_CP = 1;
                temp3  <<=1;
        }
        HC595_ST_CP = 0;//上升沿 移位寄存器的数据移到存储寄存器
        HC595_ST_CP = 1;

        HC595_SH_CP = 0;//拉低,提高抗干扰
        HC595_ST_CP = 0;
        HC595_DS = 0;

}

主函数程序:
  #include "reg51.h"
#include "hc595.h"
#include "display.h"
#include "key.h"

void Timer0Init(void);
void Timer1Init(void);
void showNormal();



unsigned char timerCnt;
unsigned char sec;
unsigned char min;
unsigned char hour;


void main()
{
        hc_595_init();
        Timer0Init();
        Timer1Init();
        EA=1;
        while(1)
        {
                TR0=1;
                showNormal();

        }


}

void showNormal()
{
        LEDBuf[0] = min/10;
        LEDBuf[1] = min%10;
        LEDBuf[2] = sec/10;
        LEDBuf[3] = sec%10;

        LEDBuf[4] = min/10;
        LEDBuf[5] = min%10;
        LEDBuf[6] = sec/10;
        LEDBuf[7] = sec%10;

        LEDBuf[8] = min/10;
        LEDBuf[9] = min%10;
        LEDBuf[10] = sec/10;
        LEDBuf[11] = sec%10;

        LEDBuf[12] = min/10;
        LEDBuf[13] = min%10;
        LEDBuf[14] = sec/10;
        LEDBuf[15] = sec%10;

        LEDBuf[16] = min/10;
        LEDBuf[17] = min%10;
        LEDBuf[18] = sec/10;
        LEDBuf[19] = sec%10;

        LEDBuf[20] = min/10;
        LEDBuf[21] = min%10;
        LEDBuf[22] = sec/10;
        LEDBuf[23] = sec%10;

        LEDBuf[24] = 0;
        LEDBuf[25] = 1;
        LEDBuf[26] = 2;


}


void Timer0Init(void)        //50微秒@12.000MHz
{
        // AUXR &=0x7F;  //定时器时钟12T模式
        TMOD &= 0xF0;    //设置定时器模式
        TMOD |= 0x01;        //设置定时器模式
        TL0 = 0xB0;        //设置定时器初始值
        TH0 = 0x3C;        //设置定时器初始值
        TF0 = 0;        //清除TF0标志
        ET0 = 1;
        EA = 1;
}

void Timer1Init(void)        //300微秒@12.000MHz
{
        // AUXR &=0xBF;  //定时器时钟12T模式
        //AUXR &= 0xBF;  //定时器时钟12T模式
        TMOD &= 0x0F;    //设置定时器模式
        TMOD |=0x10;        //设置定时器模式
        TL1 = 0xFF;        //设置定时器初始值
        TH1 = 0xFF;        //设置定时器初始值
        TF1 = 0;        //清除TF1标志
        ET1 = 1;
        TR1 = 1;
}

void timer0_ISR(void)interrupt 1
{
        timerCnt++;
        if(timerCnt >= 20)//20次1ms中断,即1S时间到
        {
                timerCnt = 0;
                sec++;
                if(sec >= 60)
                {
                        sec = 0;
                        min++;
                        if(min >=60)
                        {
                                min = 0;
                                hour++;
                                if(hour >=24)
                                {
                                        hour = 0;
                                }
                        }
                }
        }

        TL0 = 0xB0;        //设置定时器初始值
        TH0 = 0x3C;        //设置定时器初始值
}                 


void timer1_ISR(void)interrupt 3
{
        TR1 =0;
        Display();
        TL1 = 0xFF;        //设置定时器初始值
        TH1 = 0xFF;        //设置定时器初始值
        TR1 = 1;
}                 

图片1.png

27位数码管.rar

52.79 KB, 下载次数: 7

回复

使用道具 举报

ID:298743 发表于 2024-4-12 17:10 | 显示全部楼层
基本确认是写入595芯片的程序运行时间长导致的,要判断40次来写入一次数据,我在proteus仿真,程序不变每次写入数据也是判断40次,只改显示数码管的数目,只显示9位数码管的时候程序稳定,一超过9位数码管就开始闪烁了
回复

使用道具 举报

ID:298743 发表于 2024-4-12 21:07 | 显示全部楼层
可以补偿
回复

使用道具 举报

ID:79094 发表于 2024-4-12 22:00 | 显示全部楼层
小白一个 高手勿喷     增加时钟频率 可以吗
回复

使用道具 举报

ID:1109793 发表于 2024-4-13 07:12 | 显示全部楼层
595不是有控制端吗?怎么还消隐?164才需要消隐吧。我用2片595级联输出,发现市场上大部分595都不能用,只有第一片的输出逻辑正常,后面的就会比较乱。换了好几种包括安森美原装都不好使。软件无论怎样调都不行。只有一种能用的。
回复

使用道具 举报

ID:69038 发表于 2024-4-13 09:23 | 显示全部楼层
switch(i) //逐位输入数据
        {
        case 0:
                led_hc595_drive(0xffffffff,0x00);//消影 放前还是放后 要试
                temp = leddata[LEDBuf[0]];
                if(digdot0 == 1)
                {
                        temp = leddata[LEDBuf[0]] | 0x80;        //控制小数点闪烁
                }
                led_hc595_drive(PLACE_CODE[0],temp);//高位字节是位选 低位字节是断码
                                led_hc595_off(0x00);

                i++;      
                break;
====这里要以优化一下代码,找出规律,可以不用这么多的case..
回复

使用道具 举报

ID:876947 发表于 2024-4-13 13:01 | 显示全部楼层
xiaoyao166ny 发表于 2024-4-12 22:00
小白一个 高手勿喷     增加时钟频率 可以吗

我也是这样想的40M和20M 的速度肯定不同
回复

使用道具 举报

ID:105534 发表于 2024-4-13 13:40 | 显示全部楼层
xiaobendan001 发表于 2024-4-13 07:12
595不是有控制端吗?怎么还消隐?164才需要消隐吧。我用2片595级联输出,发现市场上大部分595都不能用,只 ...

那些做16*16*16光立方的是怎么用的595,参考一下
回复

使用道具 举报

ID:883242 发表于 2024-4-13 21:26 | 显示全部楼层
xiaobendan001 发表于 2024-4-13 07:12
595不是有控制端吗?怎么还消隐?164才需要消隐吧。我用2片595级联输出,发现市场上大部分595都不能用,只 ...

那就是硬件有问题,多个595地线电平不一样。
回复

使用道具 举报

ID:1110945 发表于 2024-4-13 22:07 | 显示全部楼层
想要不闪烁,得每秒刷新20次以上,也就是27个数码管在不
到50毫秒的时间里都要显示一次,每一个数码管的显示时间
不到2毫秒,5个595的数据打进去(软件法)也是要花时间的,
用硬件SPI数据传输能快一些,估计也还是会有困难。
加一片595可以让两个数码管同时显示或许会好一些。
也可以加两片595,把27个数码管分成三组,每组九个,
就很容易做了。
回复

使用道具 举报

ID:161164 发表于 2024-4-13 23:28 | 显示全部楼层
1. 不要用Long, 51算Long很耗时间的,拆开4个uchar吧
2. display里的switch太累赘了,如6楼所说的,简化一下
回复

使用道具 举报

ID:1109793 发表于 2024-4-14 07:08 | 显示全部楼层
Hephaestus 发表于 2024-4-13 21:26
那就是硬件有问题,多个595地线电平不一样。

595-2.png
麻烦帮我看看这个要怎么改才能正常使用其他品牌的595.
回复

使用道具 举报

ID:795427 发表于 2024-4-14 10:17 | 显示全部楼层
74hc595也是分型号的,例如74HC595A和75HC595D,它们使用都是存在差异,外部的硬件电路可能都不同,具体参考对应的手册。
回复

使用道具 举报

ID:883242 发表于 2024-4-14 10:25 | 显示全部楼层
xiaobendan001 发表于 2024-4-14 07:08
麻烦帮我看看这个要怎么改才能正常使用其他品牌的595.

大面积敷地可以改善问题。
回复

使用道具 举报

ID:1109793 发表于 2024-4-14 10:32 | 显示全部楼层
perseverance51 发表于 2024-4-14 10:17
74hc595也是分型号的,例如74HC595A和75HC595D,它们使用都是存在差异,外部的硬件电路可能都不同,具体参 ...

百度了一下,只是封装不一样而已。而且几个品牌如果只用一片都好使,其中最差的一个大概在几个月后会坏掉。较好的则针对自己同品牌可以用级联,但是也不稳定,偶尔出现意外的跳动,时间短的只能在LED上看到,但是继电器没有动作,长的就能听到继电器有声音,虽然强电输出也看不到,但是我认为这会影响继电器的寿命。只有一个牌子的可以,级联信号送个其他品牌都能正常稳定的输出。用示波器看了,实在看不出来问题。但是就是不好使,软件上面调整了各种顺序和延时,会略有改善,无法根除。
回复

使用道具 举报

ID:1109793 发表于 2024-4-14 10:33 | 显示全部楼层
Hephaestus 发表于 2024-4-14 10:25
大面积敷地可以改善问题。

截图里面蓝色就是铺地啊,实际上之前的板子是没有的,就是因为芯片问题才铺了,结果没什么卵用
回复

使用道具 举报

ID:619259 发表于 2024-4-14 17:19 | 显示全部楼层
27个数码管采用动态扫描,理论上是可以实现无闪显示。动态扫描刷新频率理论上不低于50Hz,能达到100Hz为最佳,扫描周期即为20-10ms。若取中间值15ms,每个数码管刷新时间为0.56ms,经仿真可以成功稳定显示,因多位数码管共用段端口,程序必须加上消隐。
回复

使用道具 举报

ID:619259 发表于 2024-4-14 22:27 | 显示全部楼层
xiaobendan001 发表于 2024-4-13 07:12
595不是有控制端吗?怎么还消隐?164才需要消隐吧。我用2片595级联输出,发现市场上大部分595都不能用,只 ...

不能怪595不好,是你没消隐造成
回复

使用道具 举报

ID:1109793 发表于 2024-4-15 07:30 | 显示全部楼层
cy009 发表于 2024-4-14 22:27
不能怪595不好,是你没消隐造成

大哥,我不是用来显示的,我是用来扩展输出的,2片级联16个输出推动三极管+继电器。这个有使能端,还有RCK,就算显示也没必要消隐吧,把数据更新到芯片,然后RCK给个上升沿,把每个芯片的数据更新到输出脚上去,这样不行吗?消隐我觉得是比如164没有RCK这种功能,在更新数据过程中每个脚都被实时更新,状态不是想要的,此时先关闭显示,等更新完成再打开,这样显示比较干净。
回复

使用道具 举报

ID:298743 发表于 2024-4-15 08:38 | 显示全部楼层
xiaobendan001 发表于 2024-4-13 07:12
595不是有控制端吗?怎么还消隐?164才需要消隐吧。我用2片595级联输出,发现市场上大部分595都不能用,只 ...

我在仿真上面的结果595级联是可以正常输出,有异常的话,你可以用keil单步调试,查看各个变量的值是怎么变化的,来查出原因
回复

使用道具 举报

ID:619259 发表于 2024-4-15 08:47 | 显示全部楼层
xiaobendan001 发表于 2024-4-15 07:30
大哥,我不是用来显示的,我是用来扩展输出的,2片级联16个输出推动三极管+继电器。这个有使能端,还有RC ...

1.595两片联级,一片传段码,一片传位码,可以不用消隐。楼主的案例是5个595,段码共用,不消隐不行呵。
2.你用595扩展输出驱动三极管+继电器,继电器电路有反峰保护吗?
回复

使用道具 举报

ID:1109793 发表于 2024-4-15 09:16 | 显示全部楼层
asdadqw2 发表于 2024-4-15 08:38
我在仿真上面的结果595级联是可以正常输出,有异常的话,你可以用keil单步调试,查看各个变量的值是怎么 ...

都说了,好的芯片是没问题的,板子不是很多,10多年前一次性买了一整盘,用了10多年,一直正常的。好不容易用完了,再买就出问题了,后级某个输出会偶尔跳动。并且几个月后会完全损坏。于是重新购买,包括在立创商城也买过,结果都不行,有的甚至直接错位输出,最后买到一种,上面的LOGO类似><的。就没问题了。我也是纳闷,这样古老的一个东西,而且大量被使用在LED点阵上面,居然还有问题。
回复

使用道具 举报

ID:1109793 发表于 2024-4-15 09:19 | 显示全部楼层
cy009 发表于 2024-4-15 08:47
1.595两片联级,一片传段码,一片传位码,可以不用消隐。楼主的案例是5个595,段码共用,不消隐不行呵。
...

1,两片显示8位和5片显示32位难道不一样吗?为啥2片不用消隐,5片就要?
2,你说的是那个二极管吗?当然有啊
回复

使用道具 举报

ID:1109793 发表于 2024-4-15 09:27 | 显示全部楼层
刚软件模拟了一下,连续输出5片的数据时间小于250us,完全可以用的。
回复

使用道具 举报

ID:1109793 发表于 2024-4-15 09:32 | 显示全部楼层
这是另外一个用了3片,一片显示数据,2片输出驱动。但是这个显示的位选是用IO的。为了配合,还是加了消隐的,先关了COM,更新数据后再打开。
  1. OP = 0;                                        //锁定输入输出
  2. dqd(OUT[0]);                //显示
  3. dqd(OUT[1]);                //OUT_1-8=>7-0
  4. dqd(OUT[2]);                //OUT_9-16=>7-0
  5. OP = 1;                                //更新输出,上升沿有效
复制代码
  1. void dqd(uchar da){
  2. //SBUF = da;
  3. //while(!TI){};
  4. //TI = 0;
  5. uchar i = 8;
  6. while(i){
  7.         MC = 0;
  8.         if(da&0x01 == 1){
  9.                 MD = 1;
  10.                 }else{
  11.                 MD = 0;
  12.                 }
  13.         da>>=1;
  14.         _nop_();_nop_();
  15.         _nop_();_nop_();
  16.         MC = 1;
  17.         _nop_();_nop_();
  18.         _nop_();_nop_();
  19.         i--;
  20.         }
  21. }
复制代码
回复

使用道具 举报

ID:298743 发表于 2024-4-15 11:26 | 显示全部楼层

能说一下怎么补偿的思路吗,我在网上找不到相关资料
回复

使用道具 举报

ID:298743 发表于 2024-4-15 11:27 | 显示全部楼层
xiaoyao166ny 发表于 2024-4-12 22:00
小白一个 高手勿喷     增加时钟频率 可以吗

我也是小白,刚刚试过改了一下long的数据分成四个,再把频率改为33.1776 就显示正常了
回复

使用道具 举报

ID:298743 发表于 2024-4-15 11:31 | 显示全部楼层
xiaobendan001 发表于 2024-4-15 09:27
刚软件模拟了一下,连续输出5片的数据时间小于250us,完全可以用的。

难道是仿真软件的问题?我在仿真软件运行这个就有闪烁
回复

使用道具 举报

ID:298743 发表于 2024-4-15 11:40 | 显示全部楼层
xiaobendan001 发表于 2024-4-15 09:32
这是另外一个用了3片,一片显示数据,2片输出驱动。但是这个显示的位选是用IO的。为了配合,还是加了消隐的 ...

这个的写法,跟我的差不多一样把,我没看出什么区别,原谅我新手不太懂
回复

使用道具 举报

ID:298743 发表于 2024-4-15 11:49 | 显示全部楼层
zhuls 发表于 2024-4-13 09:23
switch(i) //逐位输入数据
        {
        case 0:

我的想法 是switch的执行效率应该不低吧,只是占用的代码位置多而已,执行起来应该直接到相应的case里,效率来说应该还行吧。(纯新手,刚接触,希望大佬能解答一下)
回复

使用道具 举报

ID:161164 发表于 2024-4-15 13:20 | 显示全部楼层
asdadqw2 发表于 2024-4-15 11:27
我也是小白,刚刚试过改了一下long的数据分成四个,再把频率改为33.1776 就显示正常了

贴上来看看
回复

使用道具 举报

ID:1109793 发表于 2024-4-15 13:22 | 显示全部楼层
asdadqw2 发表于 2024-4-15 11:40
这个的写法,跟我的差不多一样把,我没看出什么区别,原谅我新手不太懂

应该是可以的,我这用22.1184的晶振
回复

使用道具 举报

ID:298743 发表于 2024-4-15 13:27 | 显示全部楼层
  1. void led_hc595_drive(unsigned char dat1,unsigned char dat2,unsigned char dat3,unsigned char dat4,unsigned char datL)
  2. {
  3.         unsigned char i;
  4.         unsigned char temp;
  5.         unsigned char temp2;
  6.         temp = dat1;
  7.         for(i = 0;i<8;i++)
  8.         {
  9.                 if(temp >= 0x80)   
  10.                 {
  11.                         HC595_DS = 1;
  12.                 }
  13.                 else
  14.                 {
  15.                         HC595_DS = 0;
  16.                 }
  17.                 HC595_SH_CP = 0;
  18.                 HC595_SH_CP = 1;
  19.                 temp  <<=1;
  20.         }
  21.         temp = dat2;
  22.         for(i = 0;i<8;i++)
  23.         {
  24.       
  25.                 if(temp >= 0x80)   
  26.                 {
  27.                         HC595_DS = 1;
  28.                 }
  29.                 else
  30.                 {
  31.                         HC595_DS = 0;
  32.                 }
  33.                 HC595_SH_CP = 0;
  34.                 HC595_SH_CP = 1;
  35.                 temp  <<=1;
  36.         }
  37.         temp = dat3;
  38.         for(i = 0;i<8;i++)
  39.         {
  40.          
  41.                 if(temp >= 0x80)   
  42.                 {
  43.                         HC595_DS = 1;
  44.                 }
  45.                 else
  46.                 {
  47.                         HC595_DS = 0;
  48.                 }
  49.                 HC595_SH_CP = 0;
  50.                 HC595_SH_CP = 1;
  51.                 temp  <<=1;
  52.         }
  53.         temp = dat4;
  54.         for(i = 0;i<8;i++)
  55.         {
  56.      
  57.                 if(temp >= 0x80)   
  58.                 {
  59.                         HC595_DS = 1;
  60.                 }
  61.                 else
  62.                 {
  63.                         HC595_DS = 0;
  64.                 }
  65.                 HC595_SH_CP = 0;
  66.                 HC595_SH_CP = 1;
  67.                 temp  <<=1;
  68.         }
  69.         temp2 = datL;
  70.         for(i = 0;i<8;i++)
  71.         {
  72.   
  73.                 if(temp2 >= 0x80)
  74.                 {
  75.                         HC595_DS = 1;
  76.                 }
  77.                 else
  78.                 {
  79.                         HC595_DS = 0;
  80.                 }
  81.                 HC595_SH_CP = 0;
  82.                 HC595_SH_CP = 1;
  83.                 temp2  <<=1;
  84.         }
  85.         HC595_ST_CP = 0;
  86.         HC595_ST_CP = 1;

  87.         HC595_SH_CP = 0;
  88.         HC595_ST_CP = 0;
  89.         HC595_DS = 0;

复制代码
回复

使用道具 举报

ID:298743 发表于 2024-4-15 13:37 | 显示全部楼层
xiaobendan001 发表于 2024-4-15 09:27
刚软件模拟了一下,连续输出5片的数据时间小于250us,完全可以用的。

怎么用软件模拟,我也去试下,能说一下怎么模拟的吗
回复

使用道具 举报

ID:1109793 发表于 2024-4-15 14:22 | 显示全部楼层
asdadqw2 发表于 2024-4-15 13:37
怎么用软件模拟,我也去试下,能说一下怎么模拟的吗

就是在keil里面进入调试状态,设好断点,记录时间。
回复

使用道具 举报

ID:33145 发表于 2024-4-15 15:16 | 显示全部楼层
可以尝试提高程序的效率,我用仿真24个数码管,没问题。
回复

使用道具 举报

ID:33145 发表于 2024-4-15 15:21 | 显示全部楼层
24个共阴数码管+5个74HC595,仿真软件为Proteus8.11版本,,,可以正常显示。

24位数码管显示_74HC595X5.rar

93.32 KB, 下载次数: 10

回复

使用道具 举报

ID:298743 发表于 2024-4-15 15:22 | 显示全部楼层
yqs138168 发表于 2024-4-15 15:16
可以尝试提高程序的效率,我用仿真24个数码管,没问题。

大佬能不能指点一下想法吗,我觉得我的switch虽然累赘,但是应该不影响程序执行效率,然后就到消隐和写入595的程序了,写入595的程序,我在网上找资料也只找到我这种写法,实在没什么头绪了
回复

使用道具 举报

ID:33145 发表于 2024-4-15 15:26 | 显示全部楼层
asdadqw2 发表于 2024-4-15 15:22
大佬能不能指点一下想法吗,我觉得我的switch虽然累赘,但是应该不影响程序执行效率,然后就到消隐和写入 ...

看看我的程序,新思路,与你的写法不一样,效率高很多
回复

使用道具 举报

ID:33145 发表于 2024-4-15 15:28 | 显示全部楼层
asdadqw2 发表于 2024-4-15 15:22
大佬能不能指点一下想法吗,我觉得我的switch虽然累赘,但是应该不影响程序执行效率,然后就到消隐和写入 ...

51单片机处理大的数值(特别是32位)或浮点数,效率都很低,尽可能使用char数据或位数据,提高效率,,,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表