Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, 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,070 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).
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.
69,996 views.
Postings by administrators only.
Refresh page
top