Driving a 7-segment Display with a Shift Register (74HC595)

I had a post a while back about driving a 7-segment display with an Arduino. Well, as you may recall, that took a lot of pins, 8 in fact.

What if we could reduce that by 3? What if we could only use 3?

Well, let’s introduce the shift register. This is a device which can take serial I\O and convert it into parallel.

It has two clocks on it one that reads in data and the other that shifts it out.

We have an output enable, data in, and data clear line as well.

First things first, let’s look at the datasheet.

Here is the pinout:

  • QA — QH are the outputs. In our analogy, think of having a birds eye view of our entire assembly line. We can see if there are products at any location at the same time.
  • SR — this is our input. So this is what we would place next on the assembly line.
  • OE’ — This is to say if we want to view our output on QA — QH. Two things, one is the bar (or as I’ve typed a tick or prime mark), this means logical NOT. So if you do want to view the output, then you set OE to LOW, and when you don’t, you set it to HIGH.
  • SRCLR’ — Likewise, with this tick mark, when we set this pin to low, the entire register gets cleared. All values are set back to 0. In our assembly line, this would be like flipping the entire table over.

Here is a timing diagram:

This is VERY important as it tells us what’s going on.

Let’s explain this before we get too far.

The easiest is the Output Enable (OE). As you can see, when OE’ is HIGH, the output lines (QA — QH) are in an unknown state.

Likewise, we can see the output lines go to LOW when SRCLR’ is HIGH.

Since QA — QH are outputs are low, we won’t worry about them too much, we just need to observe them along the diagram.

As we can see, the SRCLK goes up and down and the RCLK goes down and up in opposite directions. We’ll go further into that later on, but for right now, just notice that that are out of phase meaning that they do not line up. In this case, they are 180° out of phase.

Now let’s look at our SER line and our SRCLK. Notice that When SER is high and when SRCLK is high, then the QA goes high! Likewise, when SER is low.

To better understand this, take a look at Table 1. You can see arrows pointing up and down. These represent the clock phases, a raising edge and a falling edge depending on which way the arrow is pointing.

Let’s build a circuit finally!

Here is our circuit, now it looks complicated, but as we can see, it takes up less pins on the Arduino.

Here is our code:


#define SER 2
#define OE 3
#define RCLK 4
#define SRCLK 5
#define SRCLR 6

void setup() {
// put your setup code here, to run once:

pinMode(SER, OUTPUT);
pinMode(OE, OUTPUT);
pinMode(RCLK, OUTPUT);
pinMode(SRCLK, OUTPUT);
pinMode(SRCLR, OUTPUT);

//Clear everything first:
digitalWrite(SRCLR, LOW);
digitalWrite(SRCLR, HIGH);

//Turn off the output
digitalWrite(OE, HIGH);

//Now, since we're using a common annode 7-segment,
//everything will be reversed, so a LOW will mean a
//segment is on.

//DP off
digitalWrite(SER, HIGH);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

//G on
digitalWrite(SER, LOW);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

//F on
digitalWrite(SER, LOW);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

//E off
digitalWrite(SER, HIGH);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

//D off
digitalWrite(SER, HIGH);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

//C On
digitalWrite(SER, LOW);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

//B On
digitalWrite(SER, LOW);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

//A Off
digitalWrite(SER, HIGH);
digitalWrite(SRCLK, LOW);
digitalWrite(SRCLK, HIGH);

//Shift to the output register
digitalWrite(RCLK, LOW);
digitalWrite(RCLK, HIGH);

digitalWrite(OE, LOW);

}

void loop() {
// put your main code here, to run repeatedly:

}

If you build, compile, and run this, then you’ll see the number 4 is displayed.

If you look, the first bit of data is our decimal point (DP), and we shift data to the left so that our last data out is our A segment. Now, go ahead and modify this so that we only have one DP on and everything else is off. Now, add an additional SRCLK and RCLK increment. You’ll see that all the segments are off! This process of data movement, where the first piece of data in becomes the first piece of data out (First In First Out\FIFO) is called a queue. Now, for international readers, you’re already familiar with this term, but for my fellow Americans, this is a line. The first person in line is the first person leaves.

You can now play with this to create a 0 — 9 counter. As a hint though, you’ll want to put a delay(####) where #### is a number (1000 = 1 second) so you can watch the number increment.

That’s all for now.

This entry was posted in Engineering and tagged , , , , . Bookmark the permalink.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.