[SOLVED] n00b missing the first bit in HC589 shift in

I finally assembled the boarduino I bought about 5 years ago and have been learning with a couple of shift registers. I got the 74HC595 SIPO working with no problems, but I can't quite get the 74HC589 PISO to work.

Here is the datasheet: http://www.onsemi.com/pub_link/Collateral/MC74HC589A-D.PDF.

I have these connections on my breadboard:

Five 10k and three 15k pull-down resistors on the 589's parallel data input pins 15,1-7.
589's pin 8 (gnd) -> arduino gnd
589's pin 9 (serial out) -> arduino d12
589's pin 10 (output enable) -> arduino gnd
589's pin 11 (shift clock) -> arduino d11
589's pin 12 (latch clock) -> arduino d10
589's pin 13 (serial shift-parallel load) -> arduino d9
589's pin 14 (serial in) - floating

Here is the code I am running:

////Pin connected to parallel load pin of 74HC589
const int loadPin_in = 9;

//Pin connected to latch clock pin of 74HC589
const int latchPin_in = 10;

//Pin connected to shift clock pin of 74HC589
const int clockPin_in = 11;

//Pin connected to Data out (QH) of 74HC589
const int dataPin_in = 12;

void setup() {     

  pinMode(loadPin_in, OUTPUT);
  pinMode(latchPin_in, OUTPUT);
  pinMode(clockPin_in, OUTPUT);

  pinMode(dataPin_in, INPUT);
  
  // set latch pin IN to low and load pin to high initially
  digitalWrite(latchPin_in, LOW);
  digitalWrite(loadPin_in, HIGH);
  
  Serial.begin(9600);
  Serial.println("start");
}

void loop() {

  // move latch from LOW to HIGH to move parallel inputs to data latch
  digitalWrite(latchPin_in, HIGH);

  // reset the latch
  digitalWrite(latchPin_in, LOW);

  // move the load pin from high to low move the data from the data latch 
  //to the shift registers
  digitalWrite(loadPin_in, LOW);

  // move the load pin from low to high to enable shifting to data pin
  digitalWrite(loadPin_in, HIGH);

  // shift the data in from the 74HC589 to a byte variable
  byte pattern = shiftIn(dataPin_in, clockPin_in, MSBFIRST);

  Serial.println(pattern);

  // wait 5 seconds and do it again
  delay(5000);
}

I am running a jumper wire from the 589's parallel inputs to arduino vcc and get these results:

| bitOrder | | | Pin wired to vcc | | | serial monitor output | | - | - | - | - | - | | MSBFIRST | | | Input A (pin 15) | | | 2 | | MSBFIRST | | | Input B (pin 01) | | | 4 | | MSBFIRST | | | Input C (pin 02) | | | 8 | | MSBFIRST | | | Input D (pin 03) | | | 16 | | MSBFIRST | | | Input E (pin 04) | | | 32 | | MSBFIRST | | | Input F (pin 05) | | | 64 | | MSBFIRST | | | Input G (pin 06) | | | 128 | | MSBFIRST | | | Input H (pin 07) | | | 0 |

I was expecting these results:

| bitOrder | | | Pin wired to vcc | | | serial monitor output | | - | - | - | - | - | | MSBFIRST | | | Input A (pin 15) | | | 1 | | MSBFIRST | | | Input B (pin 01) | | | 2 | | MSBFIRST | | | Input C (pin 02) | | | 3 | | MSBFIRST | | | Input D (pin 03) | | | 8 | | MSBFIRST | | | Input E (pin 04) | | | 16 | | MSBFIRST | | | Input F (pin 05) | | | 32 | | MSBFIRST | | | Input G (pin 06) | | | 64 | | MSBFIRST | | | Input H (pin 07) | | | 128 |

I have tried 5-20 microsecond delays between digital writes. If I wire the serial input pin to vcc, then I shiftIn returns 1. If I change the shift bitOrder to LSBFIRST, then I see:

| bitOrder | | | Pin wired to vcc | | | serial monitor output | | - | - | - | - | - | | LSBFIRST | | | Input A (pin 15) | | | 64 | | LSBFIRST | | | Input B (pin 01) | | | 32 | | LSBFIRST | | | Input C (pin 02) | | | 16 | | LSBFIRST | | | Input D (pin 03) | | | 8 | | LSBFIRST | | | Input E (pin 04) | | | 4 | | LSBFIRST | | | Input F (pin 05) | | | 2 | | LSBFIRST | | | Input G (pin 06) | | | 1 | | LSBFIRST | | | Input H (pin 07) | | | 0 | | LSBFIRST | | | Serial Input (pin 14) | | | 128 |

Am I reading the data sheet and/or timing diagram wrong or something (I am a n00b after all)? Do I need to stop using shiftIn() and handle the clock and serial read myself to make sure I pick up that first bit? Or do I need to just wire my parallel inputs to pin 14, and not pin 7?

Any help is appreciated.

I don't see anywhere in that code that outputs the text that you have there. How do we know that it's not the routine you're using to print that text that's at fault?

The output is simply the value of the byte received from the shift register:

  byte pattern = shiftIn(dataPin_in, clockPin_in, MSBFIRST);

  Serial.println(pattern);

I added the pin numbers in my output to try to make it more clear (failed).

What I meant to express was that when Input A (pin 15) is the only parallel input pin wired to vcc, the serial monitor displays the value 2, where I would have expected it to display 1. When Input B (pin 1) is the only input pin wired to vcc, the serial monitor displays the value 4, where I would have expected it to display 2, etc.

This is making me think that by the time I call shiftIn(), the data has already been shifted once.

Perhaps I should not have presented the "output" the way I did in code tags. Sorry for the confusion.

Looks like I may not be the only one: https://github.com/arduino/Arduino/pull/1541

I guess the shiftIn() function pulses the clock, then starts reading the serial output. And I guess this might be how older piso shift registers tended to function, but not the newer ones (at least according to the above referenced bug report).

I pulled the code up in github:https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/wiring_shift.c

Copied the function into my sketch, renamed it and moved the command that sets the clock HIGH after the code that reads the serial input. Reran my tests and got the expected results.

// replaces built-in shiftIn to read the first bit before pulsing the clock
uint8_t naShiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
	uint8_t value = 0;
	uint8_t i;

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

		// digitalWrite(clockPin, HIGH);  // old location of clock HIGH
		if (bitOrder == LSBFIRST)
			value |= digitalRead(dataPin) << i;
		else
			value |= digitalRead(dataPin) << (7 - i);

		digitalWrite(clockPin, HIGH);  // new location of clock HIGH
		digitalWrite(clockPin, LOW);
	}
	return value;
}

… Or just use SPI, which is hardware based simultaneous shiftIn() and shiftOut(), which you can set the mode of (clock polarity, sampling edge, etc). See http://arduino.cc/en/Reference/SPI

Thanks for the tip, I'll check out SPI.

Glad you got it working.

Might not be your only problem though....

From datasheet you linked to in original post -

SA (Pin 14) Serial data input. Data on this input is shifted into the shift register on the rising edge of the Shift Clock input if Serial Shift/Parallel Load is high. Data on this input is ignored when Serial Shift/Parallel Load is low

You have your "loadPin" set to HIGH -

  // move the load pin from low to high to enable shifting to data pin
  digitalWrite(loadPin_in, HIGH);

  // shift the data in from the 74HC589 to a byte variable   byte pattern = shiftIn(dataPin_in, clockPin_in, MSBFIRST);

And pin 14, serial input, is floating -

589's pin 14 (serial in) - floating

Usually, not a good idea...

Any inputs that are not used should be tied either high or low. CMOS inputs should never be left floating since they can be switched by external noise which may cause the IC to draw a lot more current than is necessary.

And...at any point it could be HIGH or LOW....affecting your reading since loadPin is HIGH