Howto: Using a 74HC595N shift register latch with an Atmel AVR
Using a shift register latch can increase the number of output pins your AVR can use. It takes 3 avr pins to control a 74HC595N latch. The latch in turn controls 8 output pins. The latches can be daisy chained togther. So your 3 avr pins can control multiple latches greatly increasing the number of output pins available.
The 3 avr pins that connect to that latch are pins: 14 (serial input pin), 11 (clock pin) and 12 (latch). You must first shift the bits into the latch. First set pin 14 either high or low, then set pin 11 high. This sets the first bit. You repeat this 8 times to shift in all 8 bits. After the last bit you set pin 12 high and the output pins of the latch are activated. I also connected VCC to pin 16 of the latch. The diagram below doesn't show that. I used Eagle to design the circuit and their library did not show pin 16 for some reason.
Here is some sample code:
// code by chad http://www.windmeadow.com
#include <avr/interrupt.h>
int main (void)
{
DDRB = 0xFF;
// Shift in a 1
PORTB = (1<<PINB3);
PORTB = (1<<PINB1);
// Shift in a 0
PORTB = (1>>PINB3);
PORTB = (1<<PINB1);
// Shift in a 1
PORTB = (1<<PINB3);
PORTB = (1<<PINB1);
// Shift in a 0
PORTB = (1>>PINB3);
PORTB = (1<<PINB1);
// Shift in a 1
PORTB = (1<<PINB3);
PORTB = (1<<PINB1);
// Shift in a 0
PORTB = (1>>PINB3);
PORTB = (1<<PINB1);
// Shift in a 1
PORTB = (1<<PINB3);
PORTB = (1<<PINB1);
// Shift in a 0
PORTB = (1>>PINB3);
PORTB = (1<<PINB1);
// Set the latch so the bits are sent to
// the output pins of the latch
PORTB = (1<<PINB2);
while (1) {
}
}

To chain the latches together, connect the second latch to the same pins. The only wiring difference is, pin 14 of latch 2 needs to be wired to pin 9 latch 1. The avr code is almost the same. The only difference is you shift 16 times (8 per latch) then set the latch to move the bits to the output pins of both latches.
Sample code:
#include <avr/interrupt.h>
void setlatch(int,int);
int
main (void)
{
DDRB = 0xFF;
// These two numbers will be converted to bits
// and shifted to the two latches
int num1 = 143;
int num2 = 131;
setlatch( num1, num2 );
while (1)
{
}
}
void
setlatch (int num1, int num2)
{
// Conver num1 to bits and shift out
while (num1 != 0)
{
if (num1 % 2)
{
PORTB = (1
<< PINB3);
PORTB = (1
<< PINB1);
}
else
{
PORTB = (1
>> PINB3);
PORTB = (1
<< PINB1);
}
num1 = num1 / 2;
}
// Conver num2 to bits and shift out
while (num2 != 0)
{
if (num2 % 2)
{
PORTB = (1
<< PINB3);
PORTB = (1
<< PINB1);
}
else
{
PORTB = (1
>> PINB3);
PORTB = (1
<< PINB1);
}
num2 = num2 / 2;
}
// Now that all 16 bits have been moved to the latches.
// Set the latch and have the bits go to the output pins
PORTB = (1 << PINB2);
}

Comments
Dr.Vee:
@Chad: I wanted to point out that right shift in your code is actually pointless.
Expression
(1 >> PINx)will have value of 0 for all pins EXCEPT PIN0. Please fix your code so that people won't learn by accident that:PORT = (1 << PINx); // <- set the bit x
PORT = (1 >> PINx); // <- clear the bit x
The proper way to code it would be:
PORT |= (1 << PINx); // set the bit x
PORT &= ~(1 << PINx); // clear the bit x
This way you're changing only the state of selected pin. Please also note that avr-libc defines macro _BV(x) such that you can write:
PORT |= _BV(PINx);Regards,
Dr.Vee
Anonymous:
SO JUST TO CLEAR ONE THING:
YOU ACCESS INDIVIDUAL PINS OF A PORT BY: "PINB1" etc...
so u didn't have to #define the name of the pins, but these PIN NAMES I.E. PINB1, are in the library AS PINB1??
don:
Where does one find the interrupt.h file? I have installed avr studio that comes with avr gcc and don't have it. I've looked at atmel's web site but don't see it there. I've done a number of web searches & cannot find it.
I'm looking for the atmega168 part.
thanks.
narconon:
This is the best solution that a man could find. Bravo!
angler:
you could simplify code and "standardize" (not that it
matters) by using the USI in (poorly named) 3-wire mode.
instead of PB3 use D0, instead of PB1 use UCSK. the code
supplied in the datasheet works more or less unchanged.
you still need to drive the latching explicitly, you could
view this as the 3-wire chip select.
as an aside, you should keep the data stable while creating
the clock edge, your code above seems to violate hold time
requirements...
look at the spokepov design (google it) for a cute design
that uses a trick similar to the above with some extra
complication (an spi eeprom that feeds data to the latches).
chad:
Yep, you are absolutely right. When I made this program I didn't know about USI. But I think doing it this way helps to better understand how works.
But the next time I need to use a shift register I will use USI instead.
Anonymous:
Can I use a 74HC595 to read bits into the avr or is it output-only ?
chad:
I haven't tried that, but I am pretty sure you can. My example was basically serial to parrallel and you should be able to do parallel-to-serial with the avr reading the serial input. Take a look at this web site.
http://www.play-hookey.com/digital/shift-out_register.html
thanks
chad
Anonymous:
Nice, would it be possible to do something similar whit a 4015 witch don't have a latch pin?
Anonymous:
thanks
Post new comment