The SN74HC165 shift register makes it easy to add digital input to a Teensy/Arduino. On the Arduino playground a description can be found: SN74HC165N, a Sparkfun tutorial relies on the same approach.
It always seemed strange to me that shifting in would require 4 wires, whereas shifting out can make do with three. Turns out that you only need three wires, the clock inhibit is superfluous. The tutorial mentioned refer to the timing diagram:
The way I interpret the datasheet this diagram refers to the case where there's a continuously running clock, not when you have full control over the clock. Also in the datasheet is an example of a typical application with a microcontroller:
In this example the clock inhibit (pin 15) is connected to ground and just three wires are used.
The tutorials also make use of delay() statements for timing purposes.
Using an oscilloscope I performed some tests to see whether the delay is actually required. The test setup (alle delay statements removed and clock inhibit connected to ground) is shown in the following picture:
The stripboard contains four 74HC165 shift registers for the buttons and three 74HC595 shift registers for the leds, the other buttons are on two separate boards. Alle the IC sockets have 100nF decoupling caps build in. A Teensy 3.6 is mounted on a Tall Dog extension board, it is mounted on its side for easy access to all the pins.
I'm no electrical engineer but this looks like a decent clock pulse to me. Here's a screenprint showing the clock measured at the last IC in the chain:
The clock frequency is just over 2MHz, pulse width is about 175ns. From the datasheet:
Worst case is a maximum of 6MHz and a minimum pulse width of 80ns so we're well in the clear. No need for any delays in the code.
The code running in the test:
Kind regards,
Gerrit
It always seemed strange to me that shifting in would require 4 wires, whereas shifting out can make do with three. Turns out that you only need three wires, the clock inhibit is superfluous. The tutorial mentioned refer to the timing diagram:
The way I interpret the datasheet this diagram refers to the case where there's a continuously running clock, not when you have full control over the clock. Also in the datasheet is an example of a typical application with a microcontroller:
In this example the clock inhibit (pin 15) is connected to ground and just three wires are used.
The tutorials also make use of delay() statements for timing purposes.
Code:
/* Width of pulse to trigger the shift register to read and latch.
*/
#define PULSE_WIDTH_USEC 5
BYTES_VAL_T read_shift_regs()
{
long bitVal;
BYTES_VAL_T bytesVal = 0;
/* Trigger a parallel Load to latch the state of the data lines,
*/
digitalWrite(clockEnablePin, HIGH);
digitalWrite(ploadPin, LOW);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(ploadPin, HIGH);
digitalWrite(clockEnablePin, LOW);
/* Loop to read each bit value from the serial out line
* of the SN74HC165N.
*/
for(int i = 0; i < DATA_WIDTH; i++)
{
bitVal = digitalRead(dataPin);
/* Set the corresponding bit in bytesVal.
*/
bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));
/* Pulse the Clock (rising edge shifts the next bit).
*/
digitalWrite(clockPin, HIGH);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(clockPin, LOW);
}
return(bytesVal);
}
Using an oscilloscope I performed some tests to see whether the delay is actually required. The test setup (alle delay statements removed and clock inhibit connected to ground) is shown in the following picture:
The stripboard contains four 74HC165 shift registers for the buttons and three 74HC595 shift registers for the leds, the other buttons are on two separate boards. Alle the IC sockets have 100nF decoupling caps build in. A Teensy 3.6 is mounted on a Tall Dog extension board, it is mounted on its side for easy access to all the pins.
I'm no electrical engineer but this looks like a decent clock pulse to me. Here's a screenprint showing the clock measured at the last IC in the chain:
The clock frequency is just over 2MHz, pulse width is about 175ns. From the datasheet:
Worst case is a maximum of 6MHz and a minimum pulse width of 80ns so we're well in the clear. No need for any delays in the code.
The code running in the test:
Code:
unsigned long readShiftRegisters()
{
int bitVal;
unsigned long bytesVal = 0;
// Trigger a parallel Load to latch the state of the data lines
digitalWrite(ploadPin, LOW);
digitalWrite(ploadPin, HIGH);
// Loop to read each bit value from the serial out line of the SN74HC165N.
for(int i = 0; i < DATA_WIDTH; i++)
{
bitVal = digitalRead(dataPin);
// Set the corresponding bit in bytesVal.
bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));
// Pulse the Clock (rising edge shifts the next bit).
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
return(bytesVal);
}
Kind regards,
Gerrit