The shift register is one of the vital things to learn while designing an embedded system. Using shift registers, one can increase the number of input and output pins available in any microcontroller. There are situations where you want to interface many peripherals together and keep the low system cost and reliable.
This is where the shift register come into the picture. For example, in a joystick used to play games, instead of running all the pins from the console to the joystick buttons, a shift register reduces the number of pins almost by half. This increases the reliability of the joystick and has helped in saving a lot of money in the long run.
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 LED’s 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:
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):- On this pin, the clock signal is applied. On the rising edge, when the clock rises from negative to positive, the data on the DS line is sampled, and it gets stored in the shift register. 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 and 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, 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 output.
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 HC595_DDR|=((1<<HC595_SH_CP_POS)|(1<<HC595_ST_CP_POS)|(1<<HC595_DS_POS)); } // 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 HC595_PORT|=(1<<HC595_SH_CP_POS);//HIGH HC595_PORT&=(~(1<<HC595_SH_CP_POS));//LOW } //Sends a clock pulse on ST_CP line void shiftLatch() { //Pulse the Store Clock HC595_PORT|=(1<<HC595_ST_CP_POS);//HIGH _delay_loop_1(1); HC595_PORT&=(~(1<<HC595_ST_CP_POS));//LOW _delay_loop_1(1); } /* Main High level function to write a single byte to Output shift register 74HC595. Arguments: single byte to write to the 74HC595 IC Returns: NONE Description: 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 HC595DataHigh(); } else { //MSB is 0 so output high HC595DataLow(); } 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 shiftLatch(); } /* Simple Delay function approx 0.5 seconds */ void Wait() { for(uint8_t i=0;i<50;i++) { _delay_loop_2(0); } } void main() { uint8_t led[2]={ 0b10000001, 0b11000011, }; shiftInit(); //Initialise while(1) { for(uint8_t i=0;i<2;i++) { shiftWrite(led[i]); //Write the data to shift register Wait(); //Wait } } }
Circuit diagram:-
AvrStudio project code here: OutputShiftRegPROJ