7 segment display using 3 shift registers 74HC595

Hello All,
I am working with displaying 3 digits on 3 7-segment display using 3 shift registers 74HC595, say e.g. ‘0’, ‘1’, ‘2’. All the connectiones are Common Anode.
Please find attached hand made schematic. Clock and Latch is common to all the 3 shift registers. Data is connected via Q7’ from one shift register to next.
I tried with following code:

main()
{
setup();
}

setup()
{
unsigned char digits = { 0b00111111, // Value 0
0b00001001, // Value 1
0b01011110, // Value 2
0b01011011, // Value 3
0b01101001, // Value 4
0b01110011, // Value 5
0b01110111, // Value 6
0b00011001, // Value 7
0b01111111, // Value 8
0b01111011, // Value 9
};
pinMode(latch,OUTPUT);
pinMode(data,OUTPUT);
pinMode(clock,OUTPUT);

showDisplay(digits[0]); //display digit ‘0’ on 7-segment 1
showDisplay(digits[1]); //display digit ‘1’ on 7-segment 2
showDisplay(digits[2]); //display digit ‘2’ on 7-segment 3

}

void showDisplay(unsigned char value)
{
unsigned char i;

latch_low();

for(i=0; i<8; i++)
{
data_low(); // Serial input (of 74HC595) low

if( value & 0x1 ) data_high(); // If first bit is set, switch serial input high
clk_high(); // trigger clock to shift if in.
clk_low(); // switch clock low again

value>>= 1; // shift value of sevensegment one to the left.
}

latch_high(); // All data is in the shiftregister, now latch it to put it to the output

}
I tried with this but not able to display properly all the 3 digits simultaneously on all the 3 7-segment LEDs.
Can anyone help me on this? I tried with some sample code modification based on google search, but not able to display the digits properly. I think I am doing something wrong which I am not aware of.

Regards,
Raj S.

seven_segments_using_shift_register.pdf (124 KB)

Yes, cascading using Pin 9 from one chip to another.

Randomly segments are getting ON and OFF in all the 3 7-segment LEDs. I am just trying to display ‘0’,‘1’,‘2’ in 3 7-segment LEDs.

Hi RajS

Please post all your code - use code tags (the "#" button above the row of smileys).

Randomly segments are getting ON and OFF in all the 3 7-segment LEDs

Do you mean flashing / flickering on and off? Or they come on constantly but are the wrong segments?

Are you sure that your constants in digits[] are correct? Common anode means you need a 0 to light a segment, unless your data_low() and data_high() functions invert them. And have you checked the mapping from bit position in the constant to segment in the display?

value>>= 1;         // shift value of sevensegment one to the left.

Shifting right but comment says left. Which should it be?

Regards

Ray

As per Your comments, let me put the code like this: Please correct me if I am wrong.

digits[ ]= {0b11000000,0b11111001,0b10100100}; // '0','1','2'
 
unsigned long data =  0xC0F9A4  // Value 0, Value 1, Value 2 from above binary
 
				 
unsigned char i;

latch_low();

for(i=0; i<24; i++)
{

      	if( value & (0x01<<i)  ) 
          {
             data_high();   		// If first bit is set, switch serial input high
      	  }
          else	
          {
            data_low();					// Serial input (of 74HC595) low
          }
  
                clk_high();				// trigger clock to shift if in.
	      	clk_low();				// switch clock low again
      		               
}

	latch_high();			// All data is in the shiftregister, now latch it to put it to the output
if( value & (0x01<<i)  )

Don’t know if it is all of your problem but this line is broken. 0x01<<i will be zero for any i larger than 15.

This would be better by forcing the 1 to be an unsigned long so it will have 32 bits to shift to.

if( value & (0x01UL<<i)  )

I did it...but still not getting correct display.

You are shifting the bits out from LSB to MSB of your data. So bit 0 of your data will end up in bit 7 of your third shift register, while bit 23 will go to bit 0 of your first shift register.

Try reversing the bit order of your data within each byte.

Or investigate using the shiftOut() function with MSBFIRST set.

And please post ALL your code, in case the problem is somewhere else, such as in your data_low or data_high functions.

Considering common anode, suppose I want to display '0' in bottom 7-segment , '1' in middle 7-segment & '2' in top 7-segment. Please refer my attached schematic.

Also, 595 pin aarangement is like :

Q0 = segment A Q1 = segment B Q2 = segment C Q3 = segment D Q4 = segment E Q5 = segment F Q6 = segment G Q7 = segment DP

So, in sequence 1st I have to send '0', then '1' and then '2'. So, my binary data will be :

0b11000000 - 0b11111001 - 0b10100100 // value '0','1','2' MSB--------------------------------LSB

Now, I will be shifting LSB first. So, the sequence becomes '2' -> '1' -> '0'. Can You please consider my above implementation and explain me Your last comment:

"bit 0 of your data will end up in bit 7 of your third shift register, while bit 23 will go to bit 0 of your first shift register."

The issue is with the order of bits within each byte, not the sequence of each byte with respect to the three displays.

You start by shifting out the rightmost bit of the pattern. This goes into Q0 of the shift register.

When you shift the next bit, the value in Q0 moves to Q1 and then the new bit goes into Q0.

Repeat this eight times and your first bit has ended up in Q7.

Take the example of your pattern for the digit "0", where a 0 bit means segment on:

0b11000000

Starting with the rightmost bit, after 8 shifts, the shift register will hold:

Q0 = segment A = 1 = OFF
Q1 = segment B = 1 = OFF
Q2 = segment C = 0 = ON
Q3 = segment D = 0 = ON
Q4 = segment E = 0 = ON
Q5 = segment F = 0 = ON
Q6 = segment G = 0 = ON
Q7 = segment DP = 0 = ON

OK. I understood. A point I want to bring based on Your comment: "When you shift the next bit, the value in Q0 moves to Q1 and then the new bit goes into Q0. Repeat this eight times and your first bit has ended up in Q7.". So, suppose I sent '0' digit 8 bits and then, if I continue sending bits for digit '1' - i.e. from 9th bit onward, then will the data , '0' digit, moves to 2nd shift register from pin 9 of 1st 595 ?

So, suppose I sent ‘0’ digit 8 bits and then, if I continue sending bits for digit ‘1’ - i.e. from 9th bit onward, then will the data , ‘0’ digit, moves to 2nd shift register from pin 9 of 1st 595 ?

Yes, on the 9th shift, the value in Q7 of the first register moves into Q0 of the second register, and so on. Eventually, the first bit you shift into the first register ends up on Q7 of the last register.

Ok. I will try it now.

Ok. I will try it now. I have one more query. Sometime I observe that on POWER ON, the LEDs shows the previous data. Does it really happens? How to remove the previous data on POWER ON? Also, in my circuit Latch and OE pins are tied together, so, after pulling up Latch=HIGH, do I need to pull down Latch=LOW ?

Sometime I observe that on POWER ON, the LEDs shows the previous data.

Are you powering off and on just the Arduino, or the Arduino and the shift registers? How long do you leave them switched off?

And does your program write the values to the shift registers as soon as you power on / restart the Arduino? In which case, it may look like the registers have remembered the previous values.

in my circuit Latch and OE pins are tied together

Try connecting the (active low) OE pins directly to GND.

I don't have option to change the hardware right now. Meanwhile, can I try like this:

1) Loop for 24 bit data transfer 2) pulling up Latch=HIGH 3) _delay_ms(100) 4) pull down Latch=LOW --// this makes the OE pin active.

Is my mentioned approach correct ?

That should be OK. The data will be latched into the outputs on the rising edge of the latch input. A 1ms delay should be more than enough.

Incorporating all the comments, I tried. But still not getting correct display in all the 3 LEDs. Any suggestion appreciated. I am not able to find the issue. This is my final code:

function display()
{
// {0b00000011,0b10011111, 0b00100101}; // '0','1','2'
 
unsigned long data =  0b000000111001111100100101  // Value 0, Value 1, Value 2 from above binary
			 
unsigned char i;

latch_low();

for(i=0; i<24; i++)
{

      	if( value & (0x01UL<<i)  )  // insert the LSB first
          {
             data_high();   		// If first bit is set, switch serial input high
      	  }
          else	
          {
            data_low();					// Serial input (of 74HC595) low
          }
  
                clk_high();				// trigger clock to shift if in.
	      	clk_low();				// switch clock low again
               /* I tried clock_low() then clock_high() */
      		               
}

	latch_high();
        _delay_ms(1);
       latch_low();

} //end of function

But still not getting correct display in all the 3 LEDs.

What are you seeing on the LEDs? Is it a fixed pattern or is it flickering / flashing? Or are none of the segments lighting? If it is a fixed pattern, can you post a photo of what you get.

Please post ALL your code, as requested before. What you posted does not compile, and we cannot see the definitions of your functions.

You should also try reducing the program to one display for now and shifting one byte of data out. And as a test, send a byte that has only one 0 in it. That should light just one LED segment. By changing the value of the byte and retesting, you may discover where the problems lie.

So, start with 0b11111110, then try 0b11111101, and so on.