Introduction: 74HC595 Shift Register With Arduino Uno
Recently I started project that uses 74HC595 shift register. So I wondered what is the most efficient way to transfer data to it. As 74HC595 utilizes serial interface, all what I learned will apply as well for any device that utilizes serial interface. So in this instructable I want to show different approaches to write data to device using serial interface using 74HC595 shift register as showcase. I assume that you are already familiar with 74HC595 chip. If not you can use flowing links to understand how it works.
Step 1: Hardware
As my goal only to demonstrate different approaches I connected to LEDs only 4 out of 8 outputs of 74HC595. It was enough to debug my code :) Of cause you can connect to LEDs all Qx outputs if you want better looking project :)
You can see connection on images.
It seems different datasheets have different pin names for 74HC595, so I attached pinout from datasheet I used.
74HC595 constant connections:
GND (pin 8) to ground,
Vcc (pin 16) to 5V
OE (pin 13) to ground
SRCLR (MR) (pin 10) to 5V
I used 1k resistors and 3mm LEDs.
Step 2: Simple Approach
For all approaches you will see screenshots of oscilloscope connected to circuit as proof of performance. The yellow trace is serial clock (SRCLK) and blue trace is latch signal (RCLK). Also for all approaches I will show implementation of function shiftByte() that takes single byte and writes it bit by bit (serially) to 74HC595
So simplest way to write data to shift register is as described in this tutorial. Basically it uses built in shiftOut() function to implement serial interface.In this way it takes 90 microseconds to write 8 bits. Unfortunately it is no simple way to include code, so you will find sketch in attached zip file and screenshot of shiftOut() function. This approach is ok, but relatively slow.
Step 3: Approach Using Port Commands
Better way is instead of toggling each bit use commands writing data to whole port. Like this:
PORTC &= B11111101;//Data clock low
PORTC=(PORTC&B11111010)|(x&B00000001);//set clock low and output bit 0
PORTC |= B00000100;//Serial clock high
You can find more information about port manipulation commands here
Example sketch using this approach attached.
In this way writing 8 bits takes only 4.5 microseconds. It is 20 times faster than simple approach.
The drawbacks of this approach:
- Code much less clear.
- All used Arduino pins should be on same port.
- Serial data pin of 74HC595 should be connected to least significant bit of used Arduino port
Step 4: Using Inline Assembly Code
Farther optimization can be reached by using inline assembly code. In attached sketch I was able to write 8 bits in just 2.8 microseconds. It is 32 times faster than simple approach.
You can find here good tutorial on how to use inline assembly code inside C code.
Drawbacks of this approach similar to drawbacks of previous one.
Step 5: Using Hardware SPI Interface
But the best approach in this case is to use hardware SPI interface. You can read how to use it here. Basically, it is dedicated for serial communication hardware inside chip that can be used to transfer serial data with high speed. It only takes less the one microsecond to write out all 8 bits. Sketch with example attached.
For this example connection of 74HC595 to Arduino should be different from used in all other examples.
Because this approach uses specific hardware inside Arduino, 74HC595 should be connected to specific pins as folowing:
Arduino pin 13 ( SCK) to pin 11 (SRCLK) of 74HC595 (serial shift clock)
Arduino pin A1 to pin 12 (RCLK) of 74HC595 (output latch clock) generally this one can be any pin.
Arduino pin 11 (MOSI) to pin 14 (SER) of 74HC595 (serial data in)
So this is the fastest way, and also relatively easy one.
That is all. I hope you found this instructable useful. Any comments will be appreciated.
Participated in the
Microcontroller Contest 2017