Reading 74HC165 shift registers via SPI

I want to read 74HC165 shift registers via SPI. Is Arduino's SPI.beginTransaction(SPISettings()) useful for reading 74HC165 shift registers? Arduino's SPI library says:

This library allows you to communicate with SPI devices, with the Arduino as the master device.

Are shift registers SPI devices?

In case you couldn't tell from the questions, I am new to SPI and shift registers. I just want to make sure I don't wasting time learning something I can't use on shift registers.

Thank you.

The SN74HC165N is a cool little IC that will take an input of up to 8 parallel lines and produce a single, serial output. It’s a great way to increase the number of inputs on our arduinos.

Nothing to do with SPI though

Thanks J-M-L. That’s all I needed to know.

Here is an example of SPI with 595 and 165 SPI works great with the 165.

|500x302

.

This is what you need to read the 165 with SPI.

//======================================================================
//Reads the byte from the 74HC165 register
byte read74HC165()
{
  digitalWrite (Load, LOW);        //load the push button state into the 74HC165
  asm("nop\n nop\n");              //some delay
  digitalWrite (Load, HIGH);
  digitalWrite (SSin, LOW);        //enable 74HC165 clock
  asm("nop\n nop\n");              //some delay
  byte Switches = SPI.transfer(0); //get the position
  digitalWrite (SSin, HIGH);       //disable 74HC165 clock

  return  Switches;                //switches will have the value read by then 74HC165
}
//>>>>>>>>>>>>>> END of read74HC165() <<<<<<<<<<<<<<<<<

.

I would still argue that the 165 is not a 'full' SPI device because it doesn't tri-state its output like the 125

But nicely done.

Hi LarryD.

Thanks for the schematics and code. The schematic clearly refers to SPI (MISO, MOSI). But the code does not use the Arduino SPI library. Is that because it's "bit bang" ? Does it need to be initialized by SPI.beginTransaction(SPISettings()) ?

Interesting placements of diodes on the schematic. A keyboard switch matrix has a diode on each switch for simultaneous key presses. What are the diodes on the schematic for?

This code fragment is part of a bigger sketch, and yes it uses the SPI library 'not' banging.

D1-8 prevent back feeding for two or more switch pushes. They could be replaced by resistors.

In this application, D9-16 are a 'wired or' gate to generate an interrupt on any button push.

No ghosting diodes were used in this project.

.

removed duplicate post

Thanks for the quick response LarryD. Can I get a copy of the bigger sketch? That would save me a lot of trail and error.

I am designing a split keyboard and plan to connect the two halves with eSATA cable (7 wires) * 5 wires for SPI to read daisy chained 74HC165 shift registers (up to 32 columns) * 2 wires from controller pins to strobe one row at a time (2 rows)

This design is cost effective for up to 32 keys, and has a capacity for up to 64 keys. The controller will be the Teensy LC.

See attached:

_64_ASCII_Keypad_Interrupt.ino (8.8 KB)

Thanks for attaching the code LarryD. Now I can see what is going on.

The code calls two SPI library functions:

  • SPI.begin()
  • SPI.transfer()

SPI.beginTransaction(SPISettings()) is not called.

deleted duplicate post

Good example for POSI and PISO examples using 595 and 165 chips !

Using the above example, to fill in the missing code.
Thought this might be helpful.
Does not include the 595 code though :

#include <SPI.h>

//       MISO  12
//       MOSI  11
//       SCK   13
#define  Load  9
#define  SSin  10

void  setup()
{
  Serial.begin(9600);

  pinMode(Load,OUTPUT);
  pinMode(SSin,OUTPUT);
}

void  loop()
{
  Serial.print("read74HC165 = ");
  Serial.println( read74HC165() );

  delay(300);
}

// - Reads the byte from the 74HC165 register : -
byte read74HC165()
{
  digitalWrite (Load, LOW);        //load the push button state into the 74HC165
  asm("nop\n nop\n");              //some delay

  digitalWrite (Load, HIGH);
  digitalWrite (SSin, LOW);        //enable 74HC165 clock
  asm("nop\n nop\n");              //some delay

  byte Switches = SPI.transfer(0); //get the position
  digitalWrite (SSin, HIGH);       //disable 74HC165 clock

  return  Switches;                //switches will have the value read by then 74HC165
}
//

-OK,
It seems that SSin pin Signal will act as SS for the 165 chip on the MOSI.

As, SSout pin signal would act as SS / WrtPort to specify data for the 595 chip.

Just as reference, below are links to using hc165 and hc595 on SPI bus :
http://www.gammon.com.au/forum/?id=11979
http://www.gammon.com.au/forum/?id=11518

jlsilicon: Good example for POSI and PISO examples using 595 and 165 chips !

  • Not sure that I would suggest mixing it with SPI though ...

This is an old post ;)

This works, is working very well with zero problems.

I modified the code further, to add the 74hc595, from the Schematic above.

So, the 165 is read via SPI,
and is then written back out to the 595, which should be output on its Q pins.

Ok, the Tested Modified version, with the SPI Calls to set up Mode etc :

#include <SPI.h>

/// set up the speed, data order and data mode : ///
SPISettings Settings165( 16000000, LSBFIRST, SPI_MODE3);
SPISettings Settings595( 16000000, LSBFIRST, SPI_MODE3);

/// SPI:  Arduino:    165:      595:        ///
//        MISO  12    Q7 p9                 ///
//        MOSI  11              SER p14     ///
//        SCK   13    CLK p2    SRCLK p11   ///

/// 74hc165 :                               ///
///       SSIN  p10   NCLKE p15             ///
#define   SSin  10   // - Enable Chip Read / Clock 
///       LOAD  p9    NPL p1                ///
#define   Load  9    // - Read Input Port to SPI Register 

/// 74hc595 : ///
///       SSOUT p8              RCLK p12    ///
#define   SSout 8    // - Write SPI Reg to Output Port Register 

int C = 0 ;

void  setup()
{
  Serial.begin(9600);
  Serial.print("read74HC165 : ");

  pinMode( Load  , OUTPUT );
  pinMode( SSin  , OUTPUT );
  pinMode( SSout , OUTPUT );
  
  SPI.begin();
}

void  loop()
{
  int  D = read74HC165() ;
 
  Serial.print("read74HC165 = ");
  Serial.println( D );

  /// You can just Enable either line ///
  /// The IF() just switches back and forth between displaying the counter C and the 165 Reg Input : ///
  if( C & 1 )
  {
    write74HC595( D );
  }
  else
  {
    /// TEST : ///
    write74HC595( (C >> 1) );
  }
  C ++ ;
  
  delay(300);
}

// - Reads byte from 74HC165 chip : //
byte read74HC165()
{
  digitalWrite (Load, LOW);        // - Read the push Button state into the 74HC165 SPI Reg 
  asm("nop\n nop\n");              // - delay
  digitalWrite (Load, HIGH);       // - drop Load state
  
   SPI.beginTransaction( Settings165 );
   digitalWrite (SSin, LOW);        // - Enable 74HC165 / Clock
   asm("nop\n nop\n");              // - delay

    int  Switches = SPI.transfer(0); // - Read the SPI stream 
  
   digitalWrite (SSin, HIGH);       // - Disable 74HC165 / Clock
   SPI.endTransaction();
   
  return  Switches;                // - Return Switches Value from 74HC165
}

// - Writes byte to 74HC595 chip : //
void write74HC595( int V )
{
  SPI.beginTransaction( Settings595 );
   int  DummyV = SPI.transfer( V );  // - Write / Transfer Output Data to 595 Reg 
  SPI.endTransaction();
   
    digitalWrite (SSout, HIGH);       // - Write 595 SPI Data Reg to 595 Output Port Reg 
    asm("nop\n nop\n");               // - delay
    digitalWrite (SSout, LOW);        // - drop SSout state 
}