Interfacing shift register with AVR

The shift register is one of the vital things to learn while designing an embedded system. One can increase the number of input and output pins available in any microcontroller using shift registers. There are situations where you want to interface many peripherals together and keep the low system cost and reliability.

This is where the shift register comes into the picture. For example, in a joystick used to play games, a shift register reduces the number of pins almost by half instead of running all the pins from the console to the joystick buttons.  This increases the joystick’s reliability and has helped save a lot of money in the long run.

74HC595 shift register

Another advantage of using shift register is that only three pins, mainly control, latch and serial input/output, can drive virtually any number of outputs or take inputs from a large number of the device. You might have seen different led cubes available in sizes of 4×4 or 6×6. The LEDs in those cubes are all driven by using shift registers.

In this tutorial, we will be using an output shift register 74HC595.  As the name suggests, the shift register is based on CMOS technology. Also, the output shift registers mainly convert serial input to parallel output, while an input shift register converts parallel input to serial output.

 The pin diagram of the shift register is as follows:

74HC595 shift register pin diagram

The above pin diagram has three signal lines which get connected to any microcontroller.

  • Serial Data Input (DS):- This pin is connected to any port of the microcontroller. This pin is responsible for getting the data serially from the microcontroller.
  • Shift Clock (SH_CP):- The clock signal is applied on this pin. When the clock rises from negative to positive, the data on the DS line is sampled and stored in the shift register on the rising edge. The bit on DS line is stored in the LSB (least significant place, i.e., BIT0). On next pulse, this bit moves to BIT1 location. After eight clock pulses, this bit is transferred to BIT7 (MSB place). After eight clock pulses, the Shift Register has all 8 bits of a byte and is ready to convert them to parallel.
  • Store Clock (ST_CP):– You can hold this pin LOW while you get everything set up; nothing on the display pins will change. When you are done, and everything is how you want, you pull the pin HIGH, and the 74HC595 will display the new settings. Even though we are changing values in the register in 8 steps, it looks like it was just one step.
  • MR: – Will empty the whole shift register; if pulled low, it must be pulled high to enable.
  • OE: – This pin enables the output when tied to ground, & disabled when HIGH.

The rest, Q0-Q7, are the output pins to control eight outputs.

Vcc and ground should be connected to +5v and ground, respectively.

Source code:-

#include <avr/io.h>
#include <util/delay.h>
#define HC595_PORT   PORTB
#define HC595_DDR    DDRB
#define HC595_DS_POS PB0      //Data pin (DS) pin location
#define HC595_SH_CP_POS PB1      //Shift Clock (SH_CP) pin location
#define HC595_ST_CP_POS PB2      //Store Clock (ST_CP) pin location
void shiftInit()
   //Make the Data(DS), Shift clock (SH_CP), Store Clock (ST_CP) lines output
// change data (DS)lines
#define HC595DataHigh() (HC595_PORT|=(1<<HC595_DS_POS))
#define HC595DataLow() (HC595_PORT&=(~(1<<HC595_DS_POS)))
//Sends a clock pulse on SH_CP line
void shiftPulse()
   //Pulse the Shift Clock
//Sends a clock pulse on ST_CP line
void shiftLatch()
   //Pulse the Store Clock
Main High level function to write a single byte to
Output shift register 74HC595.
   single byte to write to the 74HC595 IC
   The byte is serially transfered to 74HC595
   and then latched. The byte is then available on
   output line Q0 to Q7 of the HC595 IC.
void shiftWrite(uint8_t data)
   //Send each 8 bits serially
   //Order is MSB first
   for(uint8_t i=0;i<8;i++)
      //Output the data on DS line according to the
      //Value of MSB
      if(data & 0b10000000)
         //MSB is 1 so output high
         //MSB is 0 so output high
      shiftPulse();  //Pulse the Clock line
      data=data<<1;  //Now bring next bit at MSB position
   //Now all 8 bits have been transferred to shift register
   //Move them to output latch at one
Simple Delay function approx 0.5 seconds
void Wait()
   for(uint8_t i=0;i<50;i++)
void main()
   uint8_t led[2]={
   shiftInit(); //Initialise
      for(uint8_t i=0;i<2;i++)
         shiftWrite(led[i]);   //Write the data to shift register
         Wait();                 //Wait

Circuit diagram:-

74HC595 circuit digram with AVR

AvrStudio project code here: OutputShiftRegPROJ

There are more types of shift registers to try:

  1. Serial-in, Serial-out (SISO) Shift Register: This type of shift register has a single input and output, and data is shifted in and out one bit at a time. It can be used for data storage or serial-to-parallel conversion applications, eg. 74HC595, CD4021.
  2. Serial-in, Parallel-out (SIPO) Shift Register: This type of shift register has a single serial input and multiple parallel outputs. It can be used for applications such as LED or LCDs, or for driving multiple outputs, eg. 74HC164, and CD4094.
  3. Parallel-in, Serial-out (PISO) Shift Register: This type of shift register has multiple parallel inputs and a single serial output. It can be used for applications such as data transmission or for reading multiple inputs, eg. 74HC165, CD4021.
  4. Parallel-in, Parallel-out (PIPO) Shift Register: This type of shift register has multiple parallel inputs and outputs, and data is shifted in and out simultaneously. It can be used for data storage or parallel-to-serial conversion applications, eg. 74HC166, CD4021.
  5. Universal Shift Register: This type of shift register can operate in all four modes (SISO, SIPO, PISO, and PIPO), and can be programmed to operate in any of these modes as needed, eg. SN74LS299, CD4014.

Note that these are just a few examples of specific shift register components, and many other components can perform similar functions. The specific choice of a component will depend on factors such as

  • The required data rate,
  • Power consumption,
  • Voltage compatibility with other components.

Comments are closed.