Fads to Obsessions and Beyond...

Free domain for life, exceptional technical support, website transfer

SN74HC595 Shift Register

A SN74HC595 is interfaced to a PIC16F876A microcontroller. The SN57HC595 is used to control RGB LED's to demonstrate functionality. 64 RGB LED's are controlled via 4 x shift registers giving the full range of colours using Bit Angle Modulation (BAM) as the PWM technique.

The LED Matrix Sign project, required the control of 320 LED's. The MAX7221 was selected as it enables control of 64 individual LED's via a convenient 3-wire serial interface. The LED's used were the typical mono-coloured variety (3mm red LED's in this instance), however, the idea was to utilise RGB LED's instead. Each RGB LED is actually three LED's(1 x red, 1 x green, 1 x blue) constructed within a single package that looks like a single element. This means each RGB LED actually needs three control lines if colours are to be changed dynamically via a microprocessor or similar. Therefore, 64 RGB LED's would require 192 control lines which would appear to nicely match using 3 x MAX7221 (one each for control of the red, green and blue anodes of the RGB LED's - common cathode RGB's were being used).

However, the MAX7221 does not provide the facility to vary the brightness of individually connected LED's, just the intensity of all the connected LED's as a whole. Varying the intensity of the red, green and blue LED's within a single RGB LED is how the colours are "mixed" to produce any desired colour. The MAX7221 via simply turning RGB component LED's on or off in various combinations could then produce the seven "primary" colours. This could be sufficient for a particular display application, but since the intensity of the individual red, green and blue LED's within a single RGB differ with the same applied voltage/current (and the MAX7221 does not provide the facility for varying this on a individually connected LED basis), this simple scheme would mean the resultant colours obtained from "mixing" the component LED's within a single RGB would not necessarily give a pleasing "palette" of resultant primary colours.

A pulse width modulation (PWM) technique could be used to alter the "on" time of individual LED's, which in effect varies the intensity individually (this utilises the persistence of vision (POV) phenomenon of the human eye), and hence would allow producing any desired colour. However, if a PWM technique is required to utilise the MAX7221 (in this case for 64 x RGB LED's) a shift register (e.g. SN74HC595) is potentially a better solution (since don't need the BCD decoder function etc of the MAX7221). In particular considering that a SN74HC595 (from ebay) is in the order of $0.10/each compared to $1/each for a MAX7221. Further, a shift register rather than a part like the MAX7221 would be the component of choice if rather than LED's, the output lines were control of components such as sensors, motors etc. Therefore, the RGB LED application is a convenient test for experimenting with using a SN74HC595.

The SN74HC595 contains an 8-bit serial-in, parallel-out shift register that feeds an 8-bit D-type storage register, which can be daisy-chained requiring three control lines. This means a microprocessor using three output pins can potentially control 8, 16, 24, etc output channels. In the case of 64 x RGB LED's, 3 x SN74HC595 would be required for the red, green and blue anodes, plus an additional SN74HC595 for control of the common cathodes. A PWM technique called Bit Angle Modulation (BAM) is used to vary the "on" time of component LED's with the individual RGB LED's thus allowing any desired colour to be produced. The following sections discuss circuit layout/connection and software/firmwire using a PIC 16F876A. Whereas the test application is the control of 64 x RGB LED's, analogous circuit layout and software/firmware would allow the PIC 16F876A to control a large number of output channels utilising only three output pins.

The SN74HC595 provides the following from the datasheet:

    • 8-Bit Serial-In, Parallel-Out Shift
    • Wide Operating Voltage Range of 2 V to 6 V
    • ±6 mA Output Drive at 5 V
    • Low Input Current of 1 μA Max
    • Shift Register Has Direct Clear

Maximum ratings in the datasheet show that an individual output pin can have a maximum continuous output current of ±35 mA, but that the entire SN74HC595 can only have a maximum current of ±70 mA. In terms of driving typical LED's would then need to ensure that each channel would be limited to approximately 8mA so that if all LED's (assuming 8 connected) were on simultaneously the maximum current for the SN74HC595 is not exceeded. The following testing/prototyping was conducted with the SN74HC595 to demonstrate control of a large number of output channels using 3 x control pins on the PIC 16F876A:

    • single SN74HC595 shift register connected to 8xLED's, controlled by PIC 16F876A
    • 2 x SN74HC595 shift registers daisy-chained and connected to 16xLED's
    • 4 x SN74HC595 shift registers controlling 64 x RGB LED's; BAM PWM to produce full range of colours

See the various sections below for circuit details, schematic diagrams, software/firmware and other details

The DIY PIC Development Board was used with a PIC 16F876A. A typical "wall-wart" power-supply is used (a surplus laptop charger in this case) in conjunction with a voltage regulator (LM7805) to provide the regulated 5V required by the PIC microcontroller and the rest of the circuitry.

1 x SN74HC595 + 8 x LED's + PIC16F876A

The connection of the SN74HC595 (see Schematic Diagram section) is relatively straight forward with there being three control lines from the PIC16F876A and eight output lines from the shift register (in this case controlling a series of LED's):

    • Pin 12: RCLK - this is the data latch pin, when the voltage changes from low to high, the data in the shift register part of the SN74HC595 is transfered into the storage register part of the SN74HC595 (i.e., the output pins of the SN74HC595 now reflect the state of the input serial data, and don't change until pin 12 changes from low to high again)
    • Pin 11: SRCLK - this is the "clock" pin, when the voltage changes from low to high, the input at the serial data input pin (SER pin 14) is "clocked" into the first stage of the shift register (with data shifting to each successive stage from the previous stage)
    • Pin 10: this is the reset pin. This can be left connected to Vcc (i.e. 5V). If this is connected to a switch (or PIC microprocessor) to ground, then when pin 10 goes low, the shift register is cleared
    • Pin 9: Qh` - this is the "data out" pin. Connect pin 9 to pin 14 of the next successive SN74HC595 in order to daisy-chain shift registers
    • Pin 15 & 1 to 7: these are the output pins Qa to Qh respectively.
    • Pin 14: SER - this is the serial data input pin
    • Pin 13: OE - this is the enable pin. Connect pin 13 to ground to enable the shift register. If this is connected to a switch (or PIC microprocessor) if connected to Vcc (i.e. 5V) then the output pins are disabled, otherwise, when connected to ground, the output pins are enabled.

Connection to the PIC microprocessor utilises any convenient output pins (in this case, pins RC1, RC3 and RC5 from Port C). The connection of the PIC microprocessor to enable basic operation (i.e. power supply, crystal oscillator, ICSP etc) is detailed in the DIY PIC Development Board. Connection of the LED's, which are used as output devices to demonstrate the state of the shift register outputs, is straight forward (note the current limiting resistors).

2 x SN74HC595 daisy-chained + 16 x LED's + PIC16F876A

The connection of the shift registers is analoguous to that of a single shift register. The clock (pin 11) and data latch (pin 12) are connected from both shift registers to the appropriate pin on the PIC microcontroller (i.e. as a "bus"). The serial data output from PIC microcontroller (pin RC5 in this instance) goes to the first shift register's serial data input pin (pin 14). However, then pin 9 of the first shift register is connected to pin 14 of the second shift register (and so on if further shift registers were daisy-chained in sequence).

4 x SN74HC595 + 64 x RGB LED's + PIC16F876A

The various shift registers are connected daisy-chained together analoguous to that detailed for the two shift registers in the previous section. Pin 11 on each of the shift registers are connected together and then to the clock pin of the PIC microcontroller. Similarly, pin 12 on each of the shift registers are connected together and then to the data latch pin designated on the PIC microcontroller. The serial data output from PIC microcontroller (pin RC5 in this instance) goes to the first shift register's serial data input pin (pin 14). The pin 9 of the first shift register is connected to pin 14 of the second shift register and so on for the other two shift registers in sequence.

The major difference in the wiring of the 4 x SN74HC595 to control the 64 x RGB LED's is concerned with how the RGB LED's operate. The 4 x SN74HC595 shift registers form in effect a four byte data structure that represents the state of the RGB LED's, which in turn can be represented as a 8 x 8 matrix. Each RGB LED belongs to row and column in the matrix, while at the same time, each RGB LED physically has three anodes (one each for the red, green and blue "channel"). The first shift register is choosen to represent the blue channel, the second shift register the green channel, the third shift register the red channel, and finally the fourth shift register represents the "row" of the RGB LED matrix. The output pins of the shift registers representing the red, green and blue "channels" are connected to the respective anode pins of the RGB LED's. Thus all the blue LED anodes in column 1 of the RGB LED matrix are connected to the first output pin of the first shift register, and all the blue LED anodes in column 2 to the second output pin of the first shift register and so forth. Similarily, all the green LED anodes column 1 of the RGB LED matrix are connected to the first output pin of the second shift register, and all the blue LED anodes in column 2 to the second output pin of the second shift register and so forth. Again, similar for the red LED anodes but connecting to the third shift register. Finally, all the cathodes of the first row of the RGB LED matrix are connected to the first outpu pin of the fourth shift register, and so on for the remainder of the cathodes.

Therefore, in order to light a particular RGB LED for a particular colour, the correct bit within the fourth shift register needs to be set to select the correct cathode (i.e. connect the row to ground) and then the correct bits within the first three shift registers need to be set to select which anodes are connected to Vcc, and hence light the appropriate LED. This highlights a couple of other features of the circuit:

    • Enabling "rows" to be selected means that individual RGB LED's can be indexed selectivity, and this then allows PWM (using bit angle modulation BAM) to produce desired shades of colours
    • There is the possibility that all RGB LED's within a particular row for a particular colour (ie Red, Green or Blue LED) can be on simultaneously. This would mean ~8mA from each of the output shift register pins controlling the anodes in question, but 8x8mA returning to the shift register pin controlling the common cathodes, which exceeds the 35mA limit for an individual SN74HC595 pin. This is why the fourth shift register (assigned to controlling the common cathodes) in turn controls the output pins of the ULN2003 Darlington transistor array. The ULN2003 can handle 500mA on each pin.


The required firmware to output serial data from the PIC microcontroller to the SN74HC595 shift register is relatively straight forward. The PIC microcontroller needs to produce a "clock" signal which at each raising edge (transition from low to high) causes whatever state on the serial data pin to be "clocked" into the shift register. After the appropriate number of bits have been clocked in, then the latch pin is brought high, which causes the shift register to latch the serial input data to the shift register output pins.

The following code snippet shows the process (code snippet 1):

    #define HC595_LATCH         PIN_C1
    #define HC595_CLK           PIN_C3
    #define HC595_DATA          PIN_C5
    #define NUM_CASCADED_HC595  2
    int8 dataBuffer[NUM_CASCADED_HC595];
    void HC595_putData(BYTE* dataByte) {
       //note that due to pointers being used, the contents of dataByte are destroyed
       //during the putData call, therefore, a seperate buffer/memory location is required
       //to store serial data to be output to the shift register   
       int i;       
       for(i=1;i<=NUM_CASCADED_HC595*8;++i) {  // Clock out bits from the dataByte array
          if((*(dataByte+(NUM_CASCADED_HC595-1))&0x80)==0) //determine if the serial
             output_low(HC595_DATA);                       //output pin needs to be 
          else                                             //set high or low
          output_high(HC595_CLK); //serial data BIT on output pin clocked into shift register
       output_high(HC595_LATCH); //input serial data BYTE is latched to the output pins
    void main() {
       HC595_putData(dataBuffer); //LED's lit according to dataBuffer pattern
       do { //endless loop     
       } while (TRUE);

Bit Angle Modulation (BAM) - Pulse Width Modulation

RGB LED's are composed of three seperate LED's (a red, a green and a blue, doh!) fabricated into a single package. Hence the four pins, one for each LED "colour" and a common cathode (or anode depending upon the variety in question). When the individual LED's within a RGB LED are turned on in various combinations, the resultant mixing of colours produces the various shades/hues observed. If the individual LED's within a RGB LED can only be turned on or off, then only the seven basic colours can be achieved. If the individual LED's can be controlled to have variable intensity, then potentially any colour can be output on the RGB. Pulse width modulation (PWM) is typically used to vary the intensity. While the PIC microcontroller has the ability to produce PWM output, this is generally limited to only a few output pins (see PIC PWM for examples). In order to produce PWM via the shift registers (i.e. in effect having 192 PWM outputs) bit angle modulation (BAM) is used.

There are a number of sites giving in depth explanation of BAM (1). In short, BAM is a method for turning an output on and off for a certain proportion of a fixed time period (i.e. PWM) but using software/firmware for controlling the on/off periods, and hence enabling PWM on an arbitrary number of outputs. However, note this will be dependant upon the clock frequency/capabilities of the microcontroller, and really is only suited to applications such as control of a large number of RGB LED's, which rely upon persisence of vision (POV) of the human eye and inherently doesn't require particularly fast cycle times etc.

The BAM is implemented using interrupts generated by the PIC16F876 onboard Timer1 module. The frequency of the Timer1 interrupt varies depending upon the desired pulse width calculated by the BAM function. The interrupt routine performs/calls the BAM calculation functions before initiating the timer module again. This "loading up" of the interrupt routine is generally frowned upon as not good practice. However, in this particular application/use of Timer1 interrupts, the actual precise reproducibility of elapsed time between generated interrupts is not of primary importance.

Having the interrupt routine perform the BAM calculations enables the main programme loop to focus solely on performing required calculations/logic processing for animation of the RGB LED's etc, and the BAM calculation/control in effect becomes a "background process". Also, full 8-bits of BAM resolution is not necessary/required in practice to produce a large and pleasing array of potential colours using the RGB LED's (as viewed using the human eye). Therefore, by only using the higher nibble (4 most significant bits) of the "BAMbit" variable, only the longer time periods from Timer1 module are required. In turn this means the processing performed within the interrupt routine in effect becomes a relatively constant offset or addition, to the times calculated/produced by the Timer1 interrupt. Since the actual pulse widths required from each individual LED within the RGB LED to produce a particular desired output colour need to be tailored to the particular LED's in use in any case (as the individual LED's within the RGB LED have different inherent intensities), this time "constant" addition can be easily taken into account.

The following code snippet gives the BAM calculation function and an example of use within the main programme loop (code snippet 2):

    #include "hc595.h"   
    #define RED    2 
    #define GREEN  0
    #define BLUE   1   
    #define ROW    3
    const unsigned int16 BAMtimes[8] = {65530,65525,65515,65495,65455,65375,65215,64895}; //0.002ms
    int8 BAMbit;
    int8 BAMbitCnt;
    int8 dataBuffer[NUM_CASCADED_HC595];
    int8 interruptFlag = 0;  
    int8 RGB_R[8] = {255,255,128,000,000,000,000,255}; //approx "rainbow" of colours
    int8 RGB_G[8] = {000,128,255,255,255,128,000,255}; 
    int8 RGB_B[8] = {000,000,000,000,128,255,255,128}; 
    int8 LEDrow = 0b00000100; //MSB -> LSB = Qh -> Qa on HC595
    void calcBAM() {
       int8 LED;  
       for (LED=0;LED<8;LED++) {
          if ((RGB_R[LED] & BAMbit) == BAMbit) {
          } else {
          if ((RGB_G[LED] & BAMbit) == BAMbit) {
          } else {
          if ((RGB_B[LED] & BAMbit) == BAMbit) {
          } else {
       if (LEDrow==0) {LEDrow=0b00000100;}     
       dataBuffer[ROW] = LEDrow;
    void timer1_interrupt() { 
       //large amount of processing within interrupt routine generally
       //"bad practice" - see text for discussion
       BAMbit=BAMbit<<1; //only using "4 bit" BAM resolution 
       if (BAMbit==0) {BAMbit=0b00010000;BAMbitCnt=4;}        
    void main() {
       int i;
       int temp_R;
       int temp_G;
       int temp_B;
       BAMbit=0b00010000; //only using "4-bit" BAM
       setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); // Set Timer1 prescaler to 8 : this is the 'long' delay
       enable_interrupts(GLOBAL);      //To enable interrupts, the global interrupt bit must be set
       enable_interrupts(INT_TIMER1);  //and then the specific interrupt bits must be set
       do { 
          //main loop cycles the contents of the "colour" arrays
          //giving a scrolling rainbow effect on the RGB LED's
          for (i=1;i<8;i++) {
       } while (TRUE);

The Testing/Experimental Results Section provides some more detail.

Note: Image loading can be slow depending on server load.

  • Single SN74HC595 Interface SchematicSingle SN74HC595 Interface Schematic

    Silver Membership registration gives access to full resolution schematic diagrams.

    Single SN74HC595 Interface Schematic

  • Two SN74HC595 Daisy-chained SchematicTwo SN74HC595 Daisy-chained Schematic

    Silver Membership registration gives access to full resolution schematic diagrams.

    Two SN74HC595 Daisy-chained Schematic

  • SN74HC595 RGB LED Controller SchematicSN74HC595 RGB LED Controller Schematic

    Silver Membership registration gives access to full resolution schematic diagrams.

    SN74HC595 RGB LED Controller Schematic

This project did not require a PCB.

The construction was done using prototyping board. See the photographs and schematic diagram sections.

Qty Schematic Part-Reference Value Notes/Datasheet
1R110k1/4W, 10% 
24R2-R25330R1/4W, 10% 
Integrated Circuits
1U1PIC16F876APIC microcontroller datasheet
1U27805Linear Voltage Regulator  datasheet
4U3-U674HC595Serial-to-Parallel Shift Register datasheet
1U7ULN2003Darlington Transistor Array datasheet
64D1-D64RGB LED3mm, common cathode 
1J1CONN-H55-pin connector for ICSP
1X110MHzCrystal Oscillator
Description Downloads
HC595 Shift Register - Bill of Materials Text File Download

The initial circuit was simply a single SN74HC595 with the outputs connected to a series of red 3mm LED's, which displayed the bit pattern of a byte of data shifted in from the PIC16F876A. See code snippet 1 in the Circuit Details section and the first schematic diagram. A photograph of the circuit on breadboard is given in the Photographs section. Note the firmware code/circuit shifts the data most significant bit (MSB) first, and therefore the MSB is represented by the rightmost LED on the breadboard in photograph 1 etc.

A slightly more interesting test of the firmware code/circuit is displaying binary code decimal (BCD) on the LED's connected to the SN74HC595. The first video in the Photographs section shows the results of this test.

The code is as follows:

    #include "hc595.h"    
    int toggleOutput = 0;
    int interruptFlag = 0;
    void timer1_interrupt() {
       set_timer1(3035);  //200ms
    void main() {
       byte dataBuffer[2];
       int theCount;
       int countUp;
       int countDown;
       int theDirection;
       setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); // Set Timer1 prescaler to 8 : this is the 'long' delay
       set_timer1(3035); //200ms
       enable_interrupts(GLOBAL);      //To enable interrupts, the global interrupt bit must be set
       enable_interrupts(INT_TIMER1);  //and then the specific interrupt bits must be set
       countUp = 0b10000000;
       countDown = 0b00000001;
       theDirection = 0;
       dataBuffer[0] = countDown; //MSB--LSB  Qa=LSB, Qb, Qc, to Qg=MSB
       dataBuffer[1] = countUp;
       do {    
          //this version displays BCD on 16 LED's connected via 2 x shift registers
          //on set of eight LEDs "counts ascending" the other descending  
          if (interruptFlag==1) {
          if (toggleOutput==1) {
             HC595_putData(dataBuffer); //displays 1-255 as binary on LED's
             if (theDirection==0) {
                countUp>>=1; countDown<<=1;
                if(countUp==0) {
             } else {
                countUp<<=1; countDown>>=1;
                if(countUp==0) {
             dataBuffer[0] = countDown; //MSB--LSB  Qa=LSB, Qb, Qc, to Qg=MSB
             dataBuffer[1] = countUp;
       } while (TRUE);

The use of bit angle modulation (BAM) with 4 x SN74HC595 shift registers to control 24 x RGB LED's is demonstrated in Video 3 (see schematics section for circuit etc). The circuit as constructed on the breadboard, in conjunction with the firmware, is capable of controlling 64 x RGB LEDs, however, this number of RGB LED's would have been difficult (and pointless) to demonstrate on the breadboard prototype.

Using LEDs was only initiated as a convenient test case for experimenting with controlling a large number of outputs via only 3 x control lines from the microcontroller, however, now having the circuit, some "practical" use was attempted (i.e., some sort of colourful display/mood lighting etc). See the bar sign project for further details. The major difficulties encountered revolved around trying to effectively diffuse the output from the RGB LED's to produce an asethetically pleasing effect (rather than issues with electronics/circuit etc).

The various pins on the shift register (SRCLK, OE, RCLK etc) tend not to be labelled uniformally between manufacturers. This means some parts from a particular manufacturer can have slightly different pin-outs, although the functionally is equivalent. Ensure the datasheet is double checked so that the correct pins are being used for the clock, serial data in, chip enable etc.

The timing requirements are detailed in the datasheet with a maximum clock frequency of 25MHz at 4.5V (allowable maximum clock frequency increases with increasing Vcc). The SN74HC595 was successfully used with the PIC 16F876A running at 10MHz. If alternate microcontrollers operating at higher frequencies are used, perhaps timing issues can arise and would need to be checked.

The value of the current limiting resistors was initially calculated using the forward voltage of the individual LED's in the RGB LED from the datasheet and taking into account that the individual output pins on the SN74HC595 have a limit of 35mA, with the entire SN74HC595 having a maximum current limit of 70mA. However, since a pulse width modulation technique is used to produce/mix the colours from the individual LED's in a RGB LED, the effective current through the LED's was found to be approximately half of that initially calculated (assuming the LED's would be either on or off, rather than PWM). Physicaly measuring the current through the LED drive circuit showed the current limiting resistors could be halfed from that calculated.

The video's below show demonstrations of interfaced HC595's with PIC 16F876A using various combinations of LED's. The demonstration code is discussed in the "Background Section" above.

Video 1: HC595 Shift Register, 8xLED's displaying BCD counting

Video 2: Two HC595 Shift Registers daisy-chained (16 LED's)

Video 3: 4xHC595 Shift Registers (24 x RGB LED's)


No comments yet.

Add Comment/Question

Only Logged-In Members can add comments

"If we could sell our experiences for what they cost us, we'd all be millionaires".

Please donate any amount to help with hosting this web site.

If you subscribe (only $2/annum) you can view the site without advertisements and get emails abouts updates etc.



Only logged-in users with correct Membership Level can download.

Membership starts at only $2, so join now!