The Sparkfun tutorial website on shift registers is here: https://learn.sparkfun.com/tutorials/shift-registers
Wiring Diagram:
Waveform:
This is taken from the 74HC165 datasheet, observe that !PL needs to be LOW for certain time period.
Observe that "tw" is the time period that !PL must remain LOW.
The minimum tw is 120ns (0.12ms). In the program, we add 5ms delay by putting "delayMicroseconds(5);" after pulling !PL to LOW "(digitalWrite(shld_pin, LOW);" to ensure this requirement is met.
The Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | // HARDWARE CONNECTIONS // Connect the following pins between your Arduino and the 74HC165 chip // Connect pins D7 - D0 to 5V or GND or switches or whatever const int data_pin = 11; // Connect Pin 11 to SER_OUT (serial data out) - Pin 9 (Q7) of 74HC165 const int shld_pin = 8; // Connect Pin 8 to SH/!LD (shift or active low load) - Pin 1 (!PL) of 74HC165 const int clk_pin = 12; // Connect Pin 12 to CLK (the clock that times the shifting) - Pin 2 (CP) of 74HC165 const int ce_pin = 9; // Connect Pin 9 to !CE (clock enable, active low) - Pin 15 (!CE) of 74HC165 byte incoming; // Variable to store the 8 values loaded from the shift register // The part that runs once void setup() { // Initialize serial to gain the power to obtain relevant information, 9600 baud Serial.begin(9600); // Initialize each digital pin to either output or input // We are commanding the shift register with each pin with the exception of the serial // data we get back on the data_pin line. pinMode(shld_pin, OUTPUT); pinMode(ce_pin, OUTPUT); pinMode(clk_pin, OUTPUT); pinMode(data_pin, INPUT); // Required initial states of these two pins according to the datasheet timing diagram digitalWrite(clk_pin, HIGH); digitalWrite(shld_pin, HIGH); } // The part that runs to infinity and beyond void loop() { incoming = read_shift_regs(); // Read the shift register, it likes that // Print out the values being read from the shift register Serial.println("\nThe incoming values of the shift register are: "); Serial.println("D7 D6 D5 D4 D3 D2 D1 D0:"); print_byte(incoming); // Print every 1 and 0 that correlates with 8 through 1 of the dip switch //Serial.println(incoming, BIN); // **This way works too but leaves out the leading zeros** delay(2000); // Wait for some arbitrary amount of time } // This code is intended to trigger the shift register to grab values from its D7 - D0 inputs byte read_shift_regs(){ byte the_shifted = 0; // An 8 bit number to carry each bit value of D7 - D0 // Trigger loading the state of the A-H data lines into the shift register digitalWrite(shld_pin, LOW); delayMicroseconds(5); // Requires a delay here according to the datasheet timing diagram digitalWrite(shld_pin, HIGH); delayMicroseconds(5); // Required initial states of these two pins according to the datasheet timing diagram digitalWrite(clk_pin, HIGH); digitalWrite(ce_pin, LOW); // Enable the clock // Get D7 ~ D0 values // The function shiftIn() shifts in a byte (8-bit) of data one bit at a time staring from either the most (leftmost) or the least (rightmost) significant bit. the_shifted = shiftIn(data_pin, clk_pin, MSBFIRST); digitalWrite(ce_pin, HIGH); // Disable the clock return the_shifted; } void print_byte(byte val){ // This part is a bit different from the Sparkfun code. // Reference: The Quick Reference section of Bit Math Tutorial http://playground.arduino.cc/Code/BitMath on how to isolate individual bit. Serial.print(val >> 7 & 1, BIN); // print 7th bit of val Serial.print(" "); Serial.print(val >> 6 & 1, BIN); // print 6th bit of val Serial.print(" "); Serial.print(val >> 5 & 1, BIN); // print 5th bit of val Serial.print(" "); Serial.print(val >> 4 & 1, BIN); // print 4th bit of val Serial.print(" "); Serial.print(val >> 3 & 1, BIN); // print 3th bit of val Serial.print(" "); Serial.print(val >> 2 & 1, BIN); // print 2th bit of val Serial.print(" "); Serial.print(val >> 1 & 1, BIN); // print 1th bit of val Serial.print(" "); Serial.println(val >> 0 & 1, BIN); // print 0th bit of val // the above code can be written as follow //int i; for (int i = 8; i > 0; i--){ Serial.print(val >> (i - 1) & 1, BIN); Serial.print(" "); } Serial.print("\n"); } |
The Result:
Note:
D7 ~ D0 are corresponding to the pinout of 74HC165, not the label on the dip switch.
References:
- Arduino - print(), http://www.arduino.cc/en/Serial/Print
- Arduino - bitshift right (>>), http://www.arduino.cc/en/Reference/Bitshift
- Arduino - bitwise AND (&), http://www.arduino.cc/en/Reference/BitwiseAnd
- 74HC165 datasheet - http://www.nxp.com/documents/data_sheet/74HC_HCT165.pdf
--------------------------------------------------------------------------------------------------------------------------
Working with ESP8266 and 74HC165 on 3.3V
The section below is added on Jan. 17, 2020 to show how to interface ESP8266 (WeMos D1 Mini) with 74HC165 and have them working on 3.3V.
The Schematic
The Code
It's basically the same as the one above with minor changes to the pin assignment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | // HARDWARE CONNECTIONS // Connect the following pins between your Arduino and the 74HC165 chip // Connect pins D7 - D0 to 5V or GND or switches or whatever const int data_pin = 4; // Connect WeMos D1 Mini D2 pin (GPIO4) to SER_OUT (serial data out) - Pin 9 (Q7) of 74HC165 const int shld_pin = 2; // Connect WeMos D1 Mini D4 pin (GPIO2) to SH/!LD (shift or active low load) - Pin 1 (!PL) of 74HC165 const int clk_pin = 5; // Connect WeMos D1 Mini D1 pin (GPIO5) to CLK (the clock that times the shifting) - Pin 2 (CP) of 74HC165 const int ce_pin = 0; // Connect WeMos D1 Mini D3 (GPIO0) to !CE (clock enable, active low) - Pin 15 (!CE) of 74HC165 byte incoming; // Variable to store the 8 values loaded from the shift register // The code below triggers the shift register to grab values from its D7 - D0 inputs // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ byte read_shift_regs(){ byte the_shifted = 0; // An 8-bit number to carry each bit value of D7 - D0 // Trigger loading the state of the A-H data lines into the shift register digitalWrite(shld_pin, LOW); delayMicroseconds(5); // Requires a delay here according to the datasheet timing diagram digitalWrite(shld_pin, HIGH); delayMicroseconds(5); // Required initial states of these two pins according to the datasheet timing diagram digitalWrite(clk_pin, HIGH); digitalWrite(ce_pin, LOW); // Enable the clock // Get D7 ~ D0 values // The function shiftIn() shifts in a byte (8-bit) of data one bit at a time staring from either the most (leftmost) or the least (rightmost) significant bit. the_shifted = shiftIn(data_pin, clk_pin, MSBFIRST); digitalWrite(ce_pin, HIGH); // Disable the clock return the_shifted; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void print_byte(byte val){ // This part is a bit different from the Sparkfun code. // Reference: The Quick Reference section of Bit Math Tutorial http://playground.arduino.cc/Code/BitMath on how to isolate individual bit. /* Serial.print(val >> 7 & 1, BIN); // print 7th bit of val Serial.print(" "); Serial.print(val >> 6 & 1, BIN); // print 6th bit of val Serial.print(" "); Serial.print(val >> 5 & 1, BIN); // print 5th bit of val Serial.print(" "); Serial.print(val >> 4 & 1, BIN); // print 4th bit of val Serial.print(" "); Serial.print(val >> 3 & 1, BIN); // print 3th bit of val Serial.print(" "); Serial.print(val >> 2 & 1, BIN); // print 2th bit of val Serial.print(" "); Serial.print(val >> 1 & 1, BIN); // print 1th bit of val Serial.print(" "); Serial.println(val >> 0 & 1, BIN); // print 0th bit of val */ // the above code can be written as follow //int i; for (int i = 8; i > 0; i--) { Serial.print(val >> (i - 1) & 1, BIN); Serial.print(" "); } Serial.print("\n"); } void setup() { Serial.begin(115200); // Initialize each digital pin to either output or input // We are commanding the shift register with each pin with the exception of the serial // data we get back on the data_pin line. pinMode(shld_pin, OUTPUT); pinMode(ce_pin, OUTPUT); pinMode(clk_pin, OUTPUT); pinMode(data_pin, INPUT); // Initialize the below two pins according to the datasheet timing diagram digitalWrite(clk_pin, HIGH); digitalWrite(shld_pin, HIGH); } void loop(){ incoming = read_shift_regs(); // Read the shift register, it likes that // Print out the values being read from the shift register Serial.println("\nThe incoming values of the shift register are: "); Serial.println("D7 D6 D5 D4 D3 D2 D1 D0:"); print_byte(incoming); // Print every 1 and 0 that correlates with 8 through 1 of the dip switch //Serial.println(incoming, BIN); // **This way works too but leaves out the leading zeros** delay(2000); // Wait for some arbitrary amount of time } |
The Result