How to Add More Digital GPIO Pins to Arduino Projects using Shift Registers
2022-06-29 | By Maker.io Staff
Most popular low-cost development boards, like the Arduino UNO or Arduino Nano range of devices, have a relatively limited number of general-purpose input-output (GPIO) pins you can use in your projects. This means that more complicated components - like a character LCD - can quickly occupy most of the I/O lines a development board offers. Adding switches and other similar inputs to a project also poses a similar problem, and we are often limited to using only a few physical inputs.
Fortunately, there’s a way to extend both the number of inputs as well as outputs available for custom projects using standard logic ICs. Join us as we take a look at how to extend the number of GPIO pins in your Arduino projects!
Understanding the Types of Shift Registers
Shift registers are classified by how data moves in and out of the logic IC. This means that the input can be serial or parallel. Similarly, the device can shift bits out through a serial interface or multiple parallel data lines. Two common devices are serial-in-serial-out (SISO) and parallel-in-parallel-out (PIPO) shift registers. Use cases for SISO devices include line buffers, and engineers can use PIPO registers to implement a simple power-of-two operation by shifting bits left or right.
Extending the number of GPIO output lines can be done by converting serial signals to parallel lines using a serial-in-parallel-out (SIPO) register. Similarly, converting parallel lines to a single serial line using a parallel-in-serial-out (PISO) shift register allows you to extend the number of available inputs, as demonstrated in this project.
Using Shift Registers to Add Input Lines
You can use a PISO shift register to extend the number of inputs an Arduino or similar development board can read. In this approach, you connect all the inputs (for example, physical switches) to the parallel inputs of the register IC. Then, the Arduino needs to send control signals to the shift register that instruct the external part to store the input values and move them through its serial output one bit at a time. Of course, the exact control sequence and timings depend on the shift register, but they all operate similarly. Using a different shift register shouldn’t pose a problem once you understand the basic concept.
In this example, I use an SN74HC165 shift register to allow an Arduino UNO to read eight switch states using only a single digital input line:
Parallel-in-serial-out shift registers allow reading multiple inputs using only a single digital input line and two digital outputs to control the shift register.
The Arduino needs to use the clock and the SH/LD lines to control the shift register. By pulling the SH/LD input low, the register stores the state of its eight inputs. Pulling the SH/LD line high switches the register into shift mode, where it outputs a single bit at a time with every rising edge of the CLK input. Therefore, the following code allows an Arduino to read all eight input bits:
#define SH_LD 3 #define CLK 2 #define QH 5 int bits[8] = {0,0,0,0,0,0,0,0}; void sendShiftRegisterClockPulse(void) { digitalWrite(CLK, HIGH); delay(5); digitalWrite(CLK, LOW); delay(5); } void readShiftRegisterValue(void) { digitalWrite(SH_LD, LOW); delay(5); digitalWrite(SH_LD, HIGH); delay(5); for(int i = 0; i < 8; i++) { bits[i] = digitalRead(QH); sendShiftRegisterClockPulse(); } }
The sendShiftRegisterClockPulse method pulls the CLK line high before pulling it low again after five milliseconds. The readShiftRegisterValue helper method first pulls the SH_LD line low to latch the data bits in the shift register. Then, the function pulls the line high again to enable bit shifting. Lastly, the helper function reads the serial output line of the shift register eight times. It stores the result in a global integer array called bits.
Extend the Number of Outputs using Shift Registers
Similarly, you can use a SIPO shift register (for example, an SN74HC595) to extend the number of output pins in a project. A development board, such as an Arduino UNO, sends multiple bits to the shift register via a serial interface. The shift register then outputs the data bits using multiple parallel output lines:
This schematic illustrates how to use a SIPO shift register with an Arduino.
The SN74HC595 used in this example has a shifter unit and comes with a separate data register that feeds the output lines. These additional latches require a second clock signal. Furthermore, it is a tri-state device, so you can deactivate its outputs by pulling OE high. Lastly, it also comes with a clear input (SRCLR) that lets you clear the shifted bits. (It’s worth noting that I’m not using either of these two inputs in this example, since they are irrelevant for this use case.)
For this example, I connected the serial input (SER), the shift register’s clock (SRCLK), and the data register clock (RCLK). The Arduino outputs one data bit at a time using the SER line. As soon as the Arduino pulls the SRCLK line high, the shift register stores the input bit and advances the previously stored bits by one position. The Arduino needs to pull the RCLK line high once it finishes sending eight data bits into the register. Doing so will output the transmitted data over the shift register’s eight output lines (Qa through Qh):
#define SER 2 #define RCLK 3 #define SRCLK 4 void outputShiftRegisterData(void) { int data[8] = {0,1,1,0,1,0,0,1}; digitalWrite(RCLK, LOW); for(int i = 8; i >= 0; i-=1) { digitalWrite(SER, data[i]); digitalWrite(SRCLK, HIGH); delay(5); digitalWrite(SRCLK, LOW); } digitalWrite(RCLK, HIGH); }
Note that a special Arduino function called shiftOut can send an entire byte to a SIPO shift register one bit at a time with only a single call. However, I decided to include the complete loop structure in the code example above for demonstration purposes.
This image shows the SIPO example from above running in the Tinkercad Circuits online simulator.
Summary
Some projects require more digital I/O pins than a development board has to offer. In that case, you can use shift registers to extend the number of digital input and output pins of a development board, for example, an Arduino UNO.
A shift register is a standard digital logic IC that can store bit values and shift them one position at a time. You can classify these logic ICs depending on how data travels in and out of a shift register. This article discussed parallel-in-serial-out (PISO) registers suitable for extending the number of inputs of a development board. Similarly, you can use serial-in-parallel-out (SIPO) registers to expand the number of output pins.
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum