Skip to main content

Introduction to 74HC595 shift register – Controlling 16 LEDs

This tutorial shows you how to control 16 LEDs with just 3 control lines. We do this by daisy chaining 74HC595 shift registers

The 74HC595 shift register has an 8 bit storage register and an 8 bit shift register. Data is written to the shift register serially, then latched onto the storage register. The storage register then controls 8 output lines.

The figure below shows the 74HC595 pinout.

595 shift Register Pinout

Pin 14 (DS) is the Data pin. On some datasheets it is referred to as “SER”.

When pin 11 (SH_CP or SRCLK on some datasheets) goes from Low to High the value of DS is stored into the shift register and the existing values of the register are shifted to make room for the new bit.

Pin 12 (ST_CP or RCLK on some datasheets) is held low whilst data is being written to the shift register. When it goes High the values of the shift register are latched to the storage register which are then outputted to pins Q0-Q7.

The timing diagram below demonstrates how you would set the Q0-Q7 output pins to 11000011, assuming starting values of 00000000.

595 shift Register Timing

The circuit we are building is showed below, followed by the build steps

595 shift Register Circuit Diagram

We will start with an Atmega8 breadboard circuit which we have used for many of our other tutorials. We add 2 extra breadboards and route power to these.

atmega8 breadboard circuit

We add the Shift Register and connect it to +5V and Ground.

adding the shift register

We now run the following control lines between the microcontroller and Shift Register

  • PC0 to DS
  • PC1 to ST_CP
  • Pc2 to SH_CP

These are the blue wires shown below.

595 shift register breadboard circuit

Next we connect up the LEDs and resistors. I used 510 Ohm resistors, but a range of other sizes are acceptable. ohmslawcalculator.com has a great LED Resistor Calculator that you can use.

595 shift register breadboard circuit

To demonstrate the circuit, I wrote a small bit of code which produces a knight rider pattern on the 8 LEDs.

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
#include <avr/io.h>
#include <util/delay.h>
 
#define DS_PORT    PORTC
#define DS_PIN     0
#define ST_CP_PORT PORTC
#define ST_CP_PIN  1
#define SH_CP_PORT PORTC
#define SH_CP_PIN  2
 
#define DS_low()  DS_PORT&=~_BV(DS_PIN)
#define DS_high() DS_PORT|=_BV(DS_PIN)
#define ST_CP_low()  ST_CP_PORT&=~_BV(ST_CP_PIN)
#define ST_CP_high() ST_CP_PORT|=_BV(ST_CP_PIN)
#define SH_CP_low()  SH_CP_PORT&=~_BV(SH_CP_PIN)
#define SH_CP_high() SH_CP_PORT|=_BV(SH_CP_PIN)
 
//Define functions
//======================
void ioinit(void);
void output_led_state(unsigned char __led_state);
//======================
 
int main (void)
{
   ioinit(); //Setup IO pins and defaults
 
   while(1)
   {
      /*
        Output a knight rider pattern
 
        10000000
        01000000
        00100000
        00010000
        00001000
        00000100
        00000010
        00000001
        00000010
        00000100
        00001000
        00010000
        00100000
        01000000
      */
 
      for (int i=7;i>=0;i--)
      {
         output_led_state(_BV(i));
         _delay_ms(100);
      }
 
      for (int i=1;i<7;i++)
      {
         output_led_state(_BV(i));
         _delay_ms(100);
      }
   }
}
 
 
void ioinit (void)
{
    DDRC  = 0b00000111; //1 = output, 0 = input
    PORTC = 0b00000000;
}
 
void output_led_state(unsigned char __led_state)
{
   SH_CP_low();
   ST_CP_low();
   for (int i=0;i<8;i++)
   {
      if (bit_is_set(__led_state, i))
         DS_high();
      else   
         DS_low();
 
 
      SH_CP_high();
      SH_CP_low();
   }
   ST_CP_high();
}

This is all very impressive, but didn’t I say we were controlling 16 LEDs? To do this we need to add another 74HC595 shift register, more LEDs, more resistors and more orange and blue wires.

We use the Q7’ pin to daisy chain the shift registers together.

The modified circuit is shown below.

595 shift register daisy-chain circuit
dual 595 shift register breadboard circuit

To code to produce the 16 LED knight rider pattern is

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
#include <avr/io.h>
#include <util/delay.h>
 
#define DS_PORT    PORTC
#define DS_PIN     0
#define ST_CP_PORT PORTC
#define ST_CP_PIN  1
#define SH_CP_PORT PORTC
#define SH_CP_PIN  2
 
#define DS_low()  DS_PORT&=~_BV(DS_PIN)
#define DS_high() DS_PORT|=_BV(DS_PIN)
#define ST_CP_low()  ST_CP_PORT&=~_BV(ST_CP_PIN)
#define ST_CP_high() ST_CP_PORT|=_BV(ST_CP_PIN)
#define SH_CP_low()  SH_CP_PORT&=~_BV(SH_CP_PIN)
#define SH_CP_high() SH_CP_PORT|=_BV(SH_CP_PIN)
 
//Define functions
//===============================================
void ioinit(void);
void output_led_state(unsigned int __led_state);
//===============================================
 
int main (void)
{
   ioinit(); //Setup IO pins and defaults
 
   while(1)
   {
      // Output a knight rider pattern
 
      for (int i=15;i>=0;i--)
      {
         output_led_state(_BV(i));
         _delay_ms(50);
      }
      for (int i=1;i<15;i++)
      {
         output_led_state(_BV(i));
         _delay_ms(50);
      }
   }
}
 
 
void ioinit (void)
{
    DDRC  = 0b00000111; //1 = output, 0 = input
    PORTC = 0b00000000;
}
 
void output_led_state(unsigned int __led_state)
{
   SH_CP_low();
   ST_CP_low();
   for (int i=0;i<16;i++)
   {
      if ((_BV(i) & __led_state) == _BV(i))  //bit_is_set doesn’t work on unsigned int so we do this instead
         DS_high();
      else   
         DS_low();
 
 
      SH_CP_high();
      SH_CP_low();
   }
   ST_CP_high();
}

We just stopped at 16 LEDs, but we can continue daisy chaining more shift registers. This technique is not just limited to LEDs of course and we can use it to multiply output ports to drive many other kinds of devices.

One word of warning regarding this technique. When you power on the circuit, the output lines are set to some arbitrary value. Now it takes less than a microsecond to set them to your desired values, but for some circuits this may cause problems. In that case you can use to MR and OE pins to reset the storage registers.

Related News

Reading and writing Atmega168 EEPROM

EEPROM (Electrically Erasable Programmable Read Only Memory) Is non-volatile memory, meaning it persists after power...

HD44780 Character LCD Displays – Part 1

Introduction LCD character displays can be found in espresso machines, laser printers, children's toys and...

Analogue to Digital Conversion Interrupts on an ATmega168

Analogue to Digital Conversion Interrupts on an ATmega168A

Back in February, we wrote a post on Analogue to Digital Conversion. Many people mentioned...

50 Comments

  1. Compiled?

    Wondering what program you compiled with because it would not work with emacs. nice tutorial though. Thank

  2. protostackadmin Author

    Compile with GCC and AVR libc as part of winAVR

  3. rexis

    it woude great if you have some tutorial how to program and compile using winAVR.

    1. rexis

      i have the same setup but i have some problem whit code. becouse im new to microcontrolers and code i use thet code in your tutorial but winAVR, codeblocks, mikroc shows errors. i check many times if i type corect.

  4. Woody

    I have a Netduino Board and I have created this circuit. It works well for one shift register, but I do not know what to do to tell it to use the second one. Can someone tell me what I a missing? What is the programming code that signals it to use the second shift register.

    Woody

  5. anwej

    this tutorial is great. can u give schematic and program to write and display name on 8*80 LED matrix.

  6. John

    This tutorial has helped me so much. What program did you design the schematics in? They look gorgeous

  7. protostackadmin Author

    Microsoft Visio

  8. Draw program

    What program did you use for the drawing part?

  9. Ralph Hulslander

    My GCC compiler does not like:

    #define DS_low() DS_PORT&=~_BV(DS_PIN)

    What is the DS_PORT& supposed to be?

    I am sure this comes from the web posting!

    Thanks
    Ralph

  10. protostackadmin Author

    DS_PORT is defined on line 5 (#define DS_PORT PORTC).
    The &= is a compound operator (see http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B). Using the the &= operator is equivalent to

    #define DS_low() DS_PORT=DS_PORT&~_BV(DS_PIN)

    Also, there was a problem with the web posting where it was showing “&” instead of “&”. That is now fixed.

    Daniel.

    1. Ralph Hulslander

      Yeah thanks it was coming across as \&\a\m\p\; but for the actual code wanted to be just\&.

      I got both the 8 and 16 led display to work, thank you.

      Now how about 4 shift registers what do I need to do for that?

      And then how about doing patterns?

      I need to do things like 00001111111111111111000011111111 and various other patterns.

      Thanks great tutorial, it got me started, and worked first time after minor corrections to the for syntax.

      Ralph

  11. Steve

    Hi,

    I like the tutorial. I wish your sample bit pattern weren’t symmetrical so it would show which bit went to Q0 and which went to Q7. I assume first in goes to Q7, and last to Q0, right?

    Steve

  12. ibnu tohid

    Hi,

    i get this error while trying to run the code for 8 LED. I hope somebody can help me with something as i’m very new to this programming world. thanks in advance

    main.c: In function ‘main’ :
    main.c:50:11: error: stray ‘\226’ in program
    main.c:50:11: warning: statement with no effect
    make: ***[main.o] Error 1

  13. Daniel Garcia Author

    Looks like you might have a bad character ‘â’ in main.c. This might be a copy/paste issue between different encodings. Does your code look identical to the example?

    1. ibnu tohid

      yes, it is very identical. i think it look totally the same. there are no bad character in the code but the error still exist.

  14. NCM

    I would also like to know the what program you used to draw the circuits diagrams
    great tutorial!!!

    1. Daniel Garcia Author

      Mcrosoft Visio

  15. Thomas Rogers

    i was wondering if you could change it to be a parallel 74hc595 setup instead of a daisy chain by giving the digital in pins on both registers it’s own pin on the micro controller? also when you daisy chain it do you write as if there are two chips with 8 pins each or do you write as if there is 1 chip with 16 pins? like would it be two sets of 10010011 or would it be 1001001101001001? i seek wisdom in these matters…

  16. avinash kumar gupta

    great tutorial. thank you very much.
    But one thing is not clear to me. If you can help me with your command (_BV(i) & __led_state).

  17. SUDAM KAKRE

    good tutorials its of great help for beginners.

  18. weng fu

    Thanking you for the reading good article for the control the LEDs in a row. How can I make this program in the Visual Basic. The C language is not as popular as Visual Basic. I think VB can do this job better.

  19. Remco

    Hi,
    A nice article about how this shift register works. Now I know how that works!
    I have a question about the example you work with.
    While reading the NXP datasheet of the 74hc595 I noticed that the maximum current
    for the unit is 70mA and 35mA per pin.
    That indicates that it can only drive up to 3 leds (20mA) at the same time.
    Can you enlighten me why your schema works while not burning anything to a crisp?
    Thanks.
    Remco

    1. Scott

      Old question, but not all of the LEDs are on at the same time.
      Also, the author is using high value resistors (510 ohm) which reduces the current per-LED.

      Also, it’s not uncommon for people to overdrive these 595 chips to no harmful effect. This is not warranted, but if you are willing to risk your chip you can probably get away with it within reason. There are also higher-current shift-registers you can choose from.

  20. Joe

    Where you say that you use Q7 to chain the shift registers together, that does not appear to be correct, or match your schematic. Isn’t Q7 lighting an LED, and not tied to the SER of the next shift register? Should that say pin 9 QH (NOT) to pin 14 (SER) of the next shift register?

  21. Joe Ronald

    Your code did work. My Proteus also did work and simulated 16 leds. Thanks you. But 32 leds didn’t work on Proteus, because your function ‘output_led_state()’ then I did to change the type ‘unsigned int’ to ‘unsigned long’, I tried again 32 leds, but didn’t work. Help me how to run 32 leds.

  22. MRL

    Simple and clear explanation with timing diagrams.

    Thank You very much…

  23. techBOY

    code for two ic’s didn’t work, replaced the last methode with this one and got it working. (channels = number of 74HC595 connected in series)
    SH_CP_low();
    ST_CP_low();
    for (int i=0;i>=1;
    SH_CP_low();
    SH_CP_high();
    }
    ST_CP_high();

  24. Tor Øyvind

    Get compile error for that one, that &amp is not declared and what kind of function is this?

  25. supra

    What is type of variable is this _BV()?

  26. Andi

    I got the same error with Tor, the &amp is not declared.

  27. Anwej Alam

    in 16 bit LED
    use this line if((_BV(i) & __led_state) == _BV(i)) instead of if ((_BV(i) & __led_state) == _BV(i)) in line 59.

  28. Vikas Kumar

    this programm is very helpfull for mr. but how can we use this programe on 4 shift resistor. if we increase the count from 16 to 32 then it will not work . can u help me…. plz rply

  29. soso

    i want this porogram to languge c for use in codvision.
    can u help me.please.

  30. CouldYou

    I’m looking at using 10 shift registers to drive a multiplexed grid (32×16). When does proprogation become a problem? I really don’t want these 512 rgb leds to flicker. Thx! Nice presentation!

  31. HQ

    HOW TO MAKE TEXT RUNING 7 LINES 100 COLUMN WITH IC 74C595 / AT 89s 52 thanks ..

  32. CouldYou

    WHY ARE YOU YELLING? Aside from that, how are you going to power them?

  33. Damel Poone

    Can you explain how the hell the daisy-chaining works? What exactly goes to the out7′ port?

  34. Mike

    Thank you very much for this great tutorial. I had some problems controlling my led matrix because output ports of the 74hc595 were acting weird. I reviewed my complete setup with your tutorial and found that I mistakenly confused ST_CP and SH_CP.

  35. Charles Viau

    There is an art to developing a great tutorial, and you have mastered it. I wish most breadboard circuits were done as well as this. Thanks!

  36. Zoljargal

    Hello That’s Great. I made same circuit. And my circuit has one problem. I not found it. Help me!. I get 10 led on while it’s normal working. Then i get 10 or more led on while leds are off. What’s reason of this problem.

    1. Zoljargal

      I think it’s more led on what more current. 10 or more leds current affects my controller. Is it possible

  37. Ba Của Phương Linh

    In output_led_state(unsigned int __led_state) just use this:if ( i== _led_state) in line 59 and that’s all

  38. Ola Kinberg

    Hello world, I already feel this is becoming retro in the sense that my TIA chip is not retro anymore (thats pure historic) but learning Arduino to make chipsounds 2015 is already 10 years behind so.. Well Its never too late. Or? I´ve experienced a few broken links already. Maybe Im the last man on earth trying and the first one to realize Im retro retro!

  39. Jose Vasquez Garcia

    La explicación directa que facilitan ustedes en su pagina permite comprender el funcionamiento del 74HC595 cuando se desea hacer el control del encendido y apagado de 8 leds en una fila. ¿Cómo puedo hacer para que funcionen una secuencia de 50 leds RGB?. Desde Lima-Peru, agradezco anticipadamente por su deferente consideración a mi petición.

  40. Salman

    I have seven segment display which is 6digit and 16pin. i already have a pcb which is MG87FE52AE(8051)microcontroller by using IN74HC595AN shift ic i want to convert 16pin to 6pin. So i request you to please tell wiring connection and codes for access. Please reply me

Leave a reply

Shopping Cart