Controlling 6 Shift Registers

Hi!
I'm trying to use 6 74HC595 ICs and having issues controlling 5th one. I think its my code, as I re-did hardware setup on breadboard several times.
When I shift data to 5th IC, 6th one also mimics it's state for some strange reason :frowning:
Can someone help me. What am I doing wrong?
Here's the code I wrote to test setup:

  digitalWrite(SR_LATCH, LOW);
  for (int j=0; j<6; j++) {
    shiftOut(SR_DATA, SR_CLOCK, LSBFIRST, B00000000); // Zero out all 6 regs
  }
  digitalWrite(SR_LATCH, HIGH);

  digitalWrite(SR_LATCH, LOW);
  for (int j=0; j<5; j++) {
    shiftOut(SR_DATA, SR_CLOCK, LSBFIRST, B10000000); // Shift data to 5th register
  }
 digitalWrite(SR_LATCH, HIGH);
 delay (10);
 digitalWrite(SR_LATCH, LOW);
 for (int j=0; j<4; j++) {
    shiftOut(SR_DATA, SR_CLOCK, LSBFIRST, B00000000); // Zero out first 4
 }
 digitalWrite(SR_LATCH, HIGH);

This supposed to turn Port QA of 5th register to HIGH. I have LEDs connected (via resistor) to it. But when I execute it Port QA of 6th register also turns to HIGH (and another LED attached to it lights up).
Here's schematic just in case (please note OEs are already connected to ground). On this schematic I'm trying to control "CTRL18", but "CTRL34" also activates...

I think that is the expected behaviour! Your second shiftOut() loop will put 0B1000000 in the first 5 shift registers. The third shiftOut() loop will move the content of the first shift register (0B10000000) to the 5th and the contents of the second shift register (also 0B10000000) to the 6th shift register. To get a particular pattern in the 6 shift registers you need to send values for all 6 registers.

In similar situations I use shadow registers.

stowite:
I think that is the expected behaviour! Your second shiftOut() loop will put 0B1000000 in the first 5 shift registers. The third shiftOut() loop will move the content of the first shift register (0B10000000) to the 5th and the contents of the second shift register (also 0B10000000) to the 6th shift register. To get a particular pattern in the 6 shift registers you need to send values for all 6 registers.

In similar situations I use shadow registers.

Thank you! That makes sense!
What are shadow registers?

bratan:
What are shadow registers?

In your case you would allocate 6 bytes (the shadow registers) and fill them with the desired pattern for the shift registers. When you have the desired pattern in the shadows you would shift all 6 shadow bytes into the shift registers. This means you will always send 6 bytes when updating the shift registers.

Ah I see! So something like this should work?

char chadowReg [6]={B00000000,B10000000,B00000000,B00000000,B00000000,B00000000};

digitalWrite(SR_LATCH, LOW);
  for (int i=0; i<6; i++) {
    shiftOut(SR_DATA, SR_CLOCK, LSBFIRST, shadowReg[i]); 
  }
  digitalWrite(SR_LATCH, HIGH);

Yes. But update the comment :slight_smile:

stowite:
Yes. But update the comment :slight_smile:

Oops :slight_smile: Corrected. Forgot to post array as well...

Exactly. I have done the same for 45 daisy chained shift registers.
Only I used

SPI.transfer(dataArray[x]);

for much faster transfers with the SPI clock at 8 MHz.

CrossRoads:
Exactly. I have done the same for 45 daisy chained shift registers.
Only I used

SPI.transfer(dataArray[x]);

for much faster transfers with the SPI clock at 8 MHz.

45? :astonished: WOW!!! That was some project! :slight_smile:
Interesting idea about SPI. Do you have to use SPI pins for this right?

If you want high speed 8 MHz clock, yes.
To make it really fast, I coded it as 45 discrete lines:

SPDR = dataArray[0]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
SPDR = dataArray[1]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
SPDR = dataArray[2]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
:
:
SPDR = dataArray[43]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
SPDR = dataArray[44]; nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;

so each line took just 17 clocks at 16 MHz, just over 1 uS/transfer verified with logic analyzer measurements.
I found out the stream was getting interfered with, with millis() or micros() interrupts, so I turned those off during the transfer as well. Wasn't doing timing measurements, everything was based on external triggers coming in, so I wasn't using them, no loss there.

Might be lower case, spdr, I'd have to go back & look.