74HC595 Shift Register with Arduino

Article thumbnail


arduino outputs

Controlling LEDs from the 74HC595 shift register

What is a Shift Register?

A shift register loads the data on its inputs and then shifts it to its output once every clock cycle.

A shift register essentially consists of several single-bit D-Type Data Latches, one for each data bit, either a logic 0 or 1, connected together in a serial-type daisy-chain arrangement so that the output from one data latch becomes the input of the next latch.

Data bits may be fed in or out of a shift register in a serial manner, or all together at the same time in a parallel configuration.

The number of individual data latches required to make up a single shift register is usually determined by the number of bits to be stored, with the most common being 8 bits wide made from eight data latches.

Shift registers are used for the storage or movement of data. They are commonly used inside electronics to store data to convert between serial and parallel. The individual data latches that make up a single shift register are all driven by a common clock signal, making them synchronous devices.

Shift registers usually have a clear or reset connection so that they can be set or reset as needed.

What is the 74HC595?

The datasheet refers to the 74HC595 as an “8-bit serial-in, serial or parallel-out shift register with output latches; 3-state.”

From the Arduino website

74HC595 Pinout

Pin NumberPin NameFunction
1Q1Parallel data output 1
2Q2Parallel data output 2
3Q3Parallel data output 3
4Q4Parallel data output 4
5Q5Parallel data output 5
6Q6Parallel data output 6
7Q7Parallel data output 7
9Q7’Serial data output
10MRMaster reset (active low)
11SH_CPShift register clock
12ST_CPStorage register clock
13OEOutput enable (active low)
14DSSerial data input
15Q0Parallel data output 0
16VCCSupply voltage

Hardware Overview

Below is a summary of the 74HC595 and its working principles:

74HC595 summary

Before sending data to the chip, the latch pin needs to be pulled low. This is telling the register to not yet update the outputs. It will do so when latch is high again so the outputs don’t update and flicker when the data is being fed in.

The shift register has eight memory spaces, each of which can hold one bit. To set each as 1 or 0, we feed in the data using the Data and Clock pins of the chip. As a clock pulse enters the register, it means that there is a new bit to read. These are the red lines in the diagram above: the data and clock pulses need to line up so the shift register can properly count them.

The output states (in the green box) that are set high only change state when the latch pin is pulled high (indicated by another red line). This means that after all data has finished transferring, the latch pin needs to be set high to let the outputs update.

Software Overview

The 74HC595 can be controlled with the Arduino built-in function shiftOut, whose syntax is below:

shiftOut(dataPin, clockPin, bitOrder, value);

For example, to send the byte of data B10010101 LSB first to a shift register with the clock pin connected to Arduino pin 6 and data pin connected to Arduino pin 4, you would use:

shiftOut(4, 6, LSBFIRST, B10010101);

Combining this with the latch pin, assuming it is connected to Arduino pin 5, you would use:

digitalWrite(5, LOW);
shiftOut(4, 6, LSBFIRST, B10010101);
digitalWrite(5, HIGH);


All resistors are 220Ω.

74HC595 schematic


Program Flow

At the start of the program, we declare the pins used to transmit data, then set them as outputs in setup.

In loop, there are two for loops - one incrementing and one decrementing. These will make the LEDs scan back and forth.

Setting Bits and Sending Data

In the body of each loop, the out variable will be pushed out to the register. We set it to 0 (clearing all bits), then turn a single bit to 1 with bitSet. The bit number is the LED we want to turn on.

After setting the bit, we use sendData to send the byte to the register and briefly wait so the LEDs don’t change too quickly.

In the sendData function, you will see that it uses the shiftOut function in the same way explained above.