4 Daisy chained 74HC165 in 1 unsigned long

Hello,

I've tried to find many tutorials but can't seem to find one where the data is stored into an integer for example. Many tutorials use a for loop which shows the state of each bit. What I'd like to learn is how to store 4 daisy chained 74HC165 into 1 unsigned long. This should have the exact amount of space for all inputs to be high on the register.

This is my code. I can't test this yet since I only have 1 74HC165 and am still waiting for others to come.

//--Shift in--//
int latchPin = 8;
int dataPin = 9;
int clockPin = 7;
unsigned long input;
//--Shift in--//

//--Shift out--//
const int DS = 6;
const int STCP = 5;
const int SHCP = 4;
unsigned long NrOut;
//--Shift out--//

void setup() {
  //--Shift in--//
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 
  pinMode(dataPin, INPUT);
  //--Shift in--//

  //--Shift out--//
  pinMode(DS, OUTPUT); 
  pinMode(STCP, OUTPUT);
  pinMode(SHCP, OUTPUT);
  //--Shift out--//
}

void loop() {

  //--Shift in--//
  digitalWrite(latchPin,1);
  delayMicroseconds(80);
  digitalWrite(latchPin,0);
  input = shiftIn(dataPin, clockPin, MSBFIRST);
  delay(500);
  //--Shift in--//

  //--Shift out--//
  NrOut = input;
  updateShiftRegister();
  //--Shift out--//
  

}

void updateShiftRegister()
{
  digitalWrite(STCP, LOW);
  shiftOut(DS,SHCP, MSBFIRST, NrOut);
  digitalWrite(STCP, HIGH);
}

What the code does is use the shift out register 74HC595 to shift out equal amount as the input. Now you may be asking why. The shift out is only for testing. I'd like to store all 4 shift in into 1 variable which I can use for many other functions. My question is if I have done this correctly. When I

Serial.print(input,BIN);

Is the following predicted to receive when all input is low?

00000000000000000000000000000000

or same with high?

11111111111111111111111111111111

= 4.294.967.296?

My apologies in advance for this potential dumb question.

Try rewording the request.

Do you want to display a, 4 byte, unsigned long variable in 4 shift registers?

Have you read:

larryd:
Try rewording the request.

Do you want to display a, 4 byte, unsigned long variable in 4 shift registers?

I'd like to combine 4 bytes into 1 variable which will be unsigned long. My question is if it's possible and what I just did has the correct approach. What can I do better, or what is a better alternative?

I've used this as my base https://www.arduino.cc/en/Tutorial/ShftIn21

That code however, uses seperate bytes. As a test I'd like to send the same amount of input to the output. My output is 4x chained 74HC595 shift out registers. Hope this will clarify.

larryd:
Have you read:
Gammon Forum : Electronics : Microprocessors : Using a 74HC165 input shift register

Gammon Forum : Electronics : Microprocessors : Using a 74HC595 output shift register as a port-expander

Yes but it's not exactly how I have visioned it. I have no problems with the shifting out part. The 4x Chain does work and I can use something like this

NrOut = 1000;
updateShiftRegister();

Which will light up the right leds accordingly.

Look up UNION

// create a union to hold the data
union myUnion
{
    unsigned long ulNumber;
    byte ulBytes[4];
};

myUnion number;  // create an instance of the union 
number.ulNumber = 0xaabbccdd;  // assign a value to the unsigned long number

Then, number.ulBytes[0] (aa) ulBytes[1] (bb) ulBytes[2] (cc) and ulBytes[3] (dd) will be the 4 bytes that make up the unsigned long number.ulNumber variable.

Correction:
Then, number.ulBytes[0] (dd) ulBytes[1] (cc) ulBytes[2] (bb) and ulBytes[3] (aa) will be the 4 bytes that make up the unsigned long number.ulNumber variable.

larryd:
Look up UNION

// create a union to hold the data

union myUnion
{
    unsigned long ulNumber;
    byte ulBytes[4];
};

myUnion number;  // create an instance of the union
number.ulNumber = 0xaabbccdd;  // assign a value to the unsigned long number




Then, number.ulBytes[0] (aa) ulBytes[1] (bb) ulBytes[2] (cc) and ulBytes[3] (dd) will be the 4 bytes that make up the unsigned long number.ulNumber variable.

Thank you! This looks promising!

Is using UNION, thus shifting 4 times into 4 different variables, not the same as shifting 32 bit data at once, if it's even possible?

unsigned long input;

input = shiftIn(dataPin, clockPin, MSBFIRST);

A Union shares the same memory space between variables.

Run this example:

union Result
{
  unsigned long ulData;
  byte b[4];
};
Result myData;


void setup()
{
  myData.ulData = 0xaabbccdd;
  
  Serial.begin(9600);
  Serial.print("myData.ulData = ");
  Serial.print("0x");
  Serial.println(myData.ulData, HEX); 
  for(byte x = 0; x<4; x++)
  {
    Serial.print("Byte ");
    Serial.print( x );
    Serial.print (" = 0x");
    Serial.println (myData.b[x], HEX);
  }
}

void loop() 
{

}

Rather than:
input = shiftIn(dataPin, clockPin, MSBFIRST);
OR
shiftOut(DS,SHCP, MSBFIRST, NrOut);

Many here use SPI for handling shift registers, as seen in Nick Gammon's discussions.

READ
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);

Write
digitalWrite (LATCH, LOW);
SPI.transfer (0xAB);
SPI.transfer (0xCD);
SPI.transfer (0xEF);
SPI.transfer (0x42);
digitalWrite (LATCH, HIGH);

larryd:
Rather than:
input = shiftIn(dataPin, clockPin, MSBFIRST);
OR
shiftOut(DS,SHCP, MSBFIRST, NrOut);

Many here use SPI for handling shift registers, as seen in Nick Gammon's discussions.

READ
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);

Write
digitalWrite (LATCH, LOW);
SPI.transfer (0xAB);
SPI.transfer (0xCD);
SPI.transfer (0xEF);
SPI.transfer (0x42);
digitalWrite (LATCH, HIGH);

Thanks, using built in hardware is quite fast too. Am I able to use something like?

SPI.transfer(switchBank1);

This option you gave is still a bit different then what I have visioned. I've looked it up on Nick Gammon's his website but wasn't sure if I was able to compare, handle, write, etc the retrieved data. If I have read it correctly, then I should be able to

digitalWrite (LATCH, LOW);
SPI.transfer(switchBank1);
SPI.transfer(switchBank2);
SPI.transfer(switchBank3);
SPI.transfer(switchBank4);
digitalWrite (LATCH, HIGH);

Right? Does that mean I have to connect both latches of the shift in and shift out on the same SPI pin for the Arduino? It would be nice it would be versatile enough that I could use different pins for clock, latch and ds

Nicks discussion explains Daisy chaining i.e. using multiple registers.

With reference to the example in post #6 above.

You could do this:
digitalWrite (LATCH, LOW); // pulse the parallel load latch
digitalWrite (LATCH, HIGH);
myData.b[0] = SPI.transfer (0);
myData.b[1] = SPI.transfer (0);
myData.b[2] = SPI.transfer (0);
myData.b[3] = SPI.transfer (0);

You have now read the 4 bytes of external data.
Therefore, myData.ulData would be fully loaded with the needed 32 bits.

And
digitalWrite (LATCH, LOW);
SPI.transfer(myData.b[0] );
SPI.transfer(myData.b[1] );
SPI.transfer(myData.b[2] );
SPI.transfer(myData.b[3] );
digitalWrite (LATCH, HIGH);

You have now written 4 bytes i.e. myData.ulData to the output 4 byte/32 bit external register.

——> Of course you have different enables for the 32 byte input and output registers.

On second thought one reads, the other writes so one enable could be used (but I would still use 2 if pins were available :slight_smile: )