Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ Electronics ➜ Microprocessors ➜ Using a 74HC165 input shift register

Using a 74HC165 input shift register

Postings by administrators only.

Refresh page


Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Sat 23 Mar 2013 06:32 AM (UTC)

Amended on Thu 09 Oct 2014 11:35 PM (UTC) by Nick Gammon

Message
The 74HC165 lets you read 8 digital inputs quickly by shifting in all 8 bits in a single SPI instruction. You can daisy-chain them to read 16, 24, 32 or more switches or inputs at once.

You could use it, for example, to examine the settings of an 8-switch DIP switch (as a device configuration).


Tip:

The 74HC165 input shift is complementary to the 74HC595 output shift register mentioned in this posting:

http://www.gammon.com.au/forum/?id=11518


Pin outs


The pin-outs for the 74HC165 are:



You can "daisy-chain" them to connect multiple ones together, thus giving you 8, 16, 24, 32 or more extra inputs, by simply connecting the Q7 (output) bit of one register to the (DS) "data serial in" of the next.

Schematic




The 74HC165 is a bit different in operation to the 74HC595 because you have to pulse the "load" pin (1) to cause the register to load its external inputs into its internal registers.

Chip enable

I have connected the chip enable (/CE) pin to ground as the chip may as well always be enabled. Note that the MISO line is always active, thus it is not possible to share this chip with other SPI devices using the SPI hardware. You could however "bit bang" it in.

Program code


It's simple to read from the register. We let the SPI library do the hard work.

The important steps are (inside the loop function):


  • Pulse the Parallel Load pin, to load the register from the inputs
  • Do a SPI.transfer to read the chip's register



// Demo sketch to read from a 74HC165 input shift register
// Author: Nick Gammon
// Date:   23 March 2013

// Pin connections for Uno and similar:

// Chip pin 1 (/PL)  goes to LATCH (D9)  (or any other pin by changing LATCH below)
// Chip pin 2 (CP)   goes to SCK   (D13)
// Chip pin 9 (Q7)   goes to MISO  (D12)

// Pin connections for Mega2560:

// Chip pin 1 (/PL)  goes to LATCH (D9)  (or any other pin by changing LATCH below)
// Chip pin 2 (CP)   goes to SCK   (D52)
// Chip pin 9 (Q7)   goes to MISO  (D50)


#include <SPI.h>

const byte LATCH = 9;

void setup ()
{
  SPI.begin ();
  Serial.begin (115200);
  Serial.println ("Begin switch test.");
  pinMode (LATCH, OUTPUT);
  digitalWrite (LATCH, HIGH);
}  // end of setup

byte optionSwitch;
byte oldOptionSwitch; // previous state

void loop ()
{
  digitalWrite (LATCH, LOW);    // pulse the parallel load latch
  digitalWrite (LATCH, HIGH);
  optionSwitch = SPI.transfer (0);
  
  byte mask = 1;
  for (int i = 1; i <= 8; i++)
    {
    if ((optionSwitch & mask) != (oldOptionSwitch & mask))
      {
      Serial.print ("Switch ");
      Serial.print (i);
      Serial.print (" now ");
      Serial.println ((optionSwitch & mask) ? "closed" : "open");
      }  // end of bit has changed
    mask <<= 1;  
    }  // end of for each bit
  
  oldOptionSwitch = optionSwitch;
  delay (10);   // debounce
}  // end of loop


This example assumes you have wired up 8 switches to the pins (not all shown on the schematic, to save space) and reports when a switch changes.

Daisy chaining


If you want to read more than 8 switches, just use more registers, connecting 1, 2 and 15 in parallel, and the output from the "earlier" ones in the sequence (Q7) to the input of the next one (DS).

You might read four banks of switches like this:


  digitalWrite (LATCH, LOW);    // pulse the parallel load latch
  digitalWrite (LATCH, HIGH);
  switchBank1 = SPI.transfer (0);
  switchBank2 = SPI.transfer (0);
  switchBank3 = SPI.transfer (0);
  switchBank4 = SPI.transfer (0);


Pull-down resistors


Note that the switches have pull-down resistors on them to guarantee a reliable reading. Read more about that here:

http://www.gammon.com.au/switches

Data sheet


Read all about the chip here:

http://www.ti.com/lit/ds/symlink/cd74hc165.pdf

Alternatives


You can also use I2C or SPI port-expanders, such as the one described here:

http://www.gammon.com.au/forum/?id=10945

That lets you configure up to 16 pins as inputs or outputs as required.

Bit-banged SPI code


The code below uses "bit banged" SPI rather than the hardware SPI. This lets you use any pins for the shift register, perhaps keeping the SPI pins free for an SD card or other device.


// Demo sketch to read from a 74HC165 input shift register
// Author: Nick Gammon
// Date:   23 March 2013

// Pin connections for Uno and similar:

// Chip pin 1 (/PL)  goes to LATCH (D8)
// Chip pin 2 (CP)   goes to SCK   (D7)
// Chip pin 9 (Q7)   goes to MISO  (D6)

#include <bitBangedSPI.h>

bitBangedSPI bbSPI (bitBangedSPI::NO_PIN, 6, 7);  // MOSI, MISO, SCK

const byte LATCH = 8;

void setup ()
{
  bbSPI.begin ();
  Serial.begin (115200);
  Serial.println ("Begin switch test.");
  pinMode (LATCH, OUTPUT);
  digitalWrite (LATCH, HIGH);
}  // end of setup

byte optionSwitch;
byte oldOptionSwitch; // previous state

void loop ()
{
  digitalWrite (LATCH, LOW);    // pulse the parallel load latch
  digitalWrite (LATCH, HIGH);
  optionSwitch = bbSPI.transfer (0);
  
  byte mask = 1;
  for (int i = 1; i <= 8; i++)
    {
    if ((optionSwitch & mask) != (oldOptionSwitch & mask))
      {
      Serial.print ("Switch ");
      Serial.print (i);
      Serial.print (" now ");
      Serial.println ((optionSwitch & mask) ? "closed" : "open");
      }  // end of bit has changed
    mask <<= 1;  
    }  // end of for each bit
  
  oldOptionSwitch = optionSwitch;
  delay (10);   // debounce
}  // end of loop


You need to install the "bitBangedSPI" library (link below) into your libraries folder:

http://www.gammon.com.au/Arduino/bitBangedSPI.zip

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


70,618 views.

Postings by administrators only.

Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.