Monday, 23 May 2011

74HC165 PISO Shift Register - Arduino

I hate datasheet authors. There is a special place in hell for them, but that's another blog post altogether.

Anyway, for my 2D Plotter project, I need a whole bunch of user-configurable options, most of which are true/false values. So I figured on using a couple of DIP switches...

...driven by a pair of cascaded PISO shift registers.

I've used shift registers in the past but they were the SIPO type, in which a circuit supplies serial data, and at the other end parallel data is spat out. PISO does it the other way. In this case the DIP switches are hooked up to the shift registers' parallel inputs, using 10K pulldown resistors to stop the inputs floating. Then I'm using an Arduino (God, those things are omnipresent aren't they?) to control the PISO registers and read the data out.

In other words if you put a pair of octal DIP switches side by side then you can read out a 16 bit binary word from the shift registers. And that only uses 3 pins on the Arduino. In fact I still need more switches than that, so I'll just cascade probably 2 more of these shift registers and add a bunch more switches (not DIPs this time, just regular momentary microswitches). So then I'll be able to read 32 bits of switch data still using only 3 Arduino pins. Nice.

None of this is in any way even remotely clever, but I've never done this before and I suspect some of my readers haven't either.

For sanity's sake, here's the Arduino Sketch code for reading data from two 74HC165 PISO shift registers...

//The terminology used here (PL, CP, Q7 and so on) are taken DIRECTLY from the 74HC165's datasheet.

#define PIN_PL (13) //pin 13 on arduino goes to pin 1 of 74HC165
#define PIN_CP (12) //pin 12 on arduino goes to pin 2 of 74HC165
#define PIN_Q7 (11) //pin 11 on arduino goes to pin 9 of 74HC165
//Hardwire pin 15 of both 74HC165 chips to ground to enable them all the time.

//For peace of mind I also hardwired pin 10 of the upstream chip to
//GND to force zeroes to be shifted in instead of allowing it to float.
//Given that the arduino is "downstream".

void setup() 

  pinMode(PIN_PL, OUTPUT);
  pinMode(PIN_CP, OUTPUT);
  pinMode(PIN_Q7, INPUT);

  digitalWrite(PIN_PL, HIGH);
  digitalWrite(PIN_CP, LOW);

  int i;
  int j;
  int value;
  //read the switches 10 times to prove
  //that the system is stable
  for(i = 0 ; i < 10 ; i++)
    //load logic bits from the DIP switches
    digitalWrite(PIN_PL, LOW);  //LOAD BITS
    //reset "load" line, this freezes the internal buffer on both chips
    digitalWrite(PIN_PL, HIGH);
    for(j = 0 ; j < 16 ; j++)
      value = digitalRead(PIN_Q7);
      //read next "switch"
      digitalWrite(PIN_CP, HIGH);
      digitalWrite(PIN_CP, LOW);
      //print switch's value
      //put a space after the first 8 bits
        Serial.print(" ");


void loop()

Now it's about this time, where I'd have been reading YAFT (yet another *flipping* tutorial) for a bit and wondering where the schematic is...

In this diagram, the Arduino is "Even further downstream" in the circuit.

I wrote this mainly as a future reference for myself, but if it assists anyone out there then that's good too.


  1. This is a neat project Wardy, currently playing around with a counter project where the output of 4029 counters should go to the Arduino. In that case you don't need the 10k resistors on the 74HC165 IMHO.

  2. Yes I agree, the counter itself will ensure that your signals are never floating.

  3. Hi Wardy, if you are on google+ then you can see the project in full swing.