Driving 595 Shift Registers

Blog Projects
avr electronics

595 series shift registers come in many flavors. SN74HC595 is the most usual. TPIC6B595 is similar but can be used with more power hungry applications. Pin layouts are different but they all operate in the same way.

Shift register is controlled with three pins. They are usually called DATA, LATCH and CLOCK. Chip manufacturers have different names. See the table below for two examples from Texas Instruments.

74HC595 TPIC6B595
DATA SER SER IN
LATCH RCLK RCK
CLOCK SRCLK SRCK

CLOCK is an constant high – low signal used to synchronize data transfer. Each time CLOCK goes high two things happen. Current value in shift register gets shifted left by one. Last bit is dropped out. First bit will be set to current value of DATA. To write a byte to shift register this has to happen eight times in a loop.

#define LATCH   B0
#define CLOCK   B1
#define DATA    B2

void shift_out(uint8_t data) {
    for(uint8_t i = 0; i < 8; i++) {
        /* Write bit to data port. */
        if (0 == (data & _BV(7 - i))) {
            digital_write(DATA, LOW);
        } else {
            digital_write(DATA, HIGH);
        }

        /* Pulse clock input to write next bit. */
        digital_write(CLOCK, LOW);
        digital_write(CLOCK, HIGH);
    }
}

After calling shift_out() the shift register internally contains new value. To update output pins you must pull LATCH high. This is sometimes called latching on pulsing the latch. Note that it is not enough to hold LATCH high. Data transfer happens on transition from low to high. This is also called rising edge. Code for a led binary counter from 0 to 65535 would look like the following:

int main(void) {

    for(uint16_t i = 0; i < 0xffff; i++) {
        /* Shift high byte first to shift registers. */
        shift_out(i >> 8);
        shift_out(i & 0xff);

        /* Pulse latch to transfer data from shift registers */
        /* to storage registers. */
        digital_write(LATCH, LOW);
        digital_write(LATCH, HIGH);

        _delay_ms(50);
    }

    return 0;
}

The technique above is called bit banging. Bit banging is a technique for serial communications using software instead of dedicated hardware. Good thing is it is cheap to implement. Bad thing is it wastes processing time. Luckily most AVR chips provide an alternative.

Serial Peripheral Interface Bus

The Serial Peripheral Interface Bus or SPI is a synchronous serial data connection. It provides hardware implementation of the clock pulse and writing data serially. SPI terminology differs from bit banging a bit. You can use SPI with three pins only. If you also want to read value back from the slave device you must use fourth pin. This is what MISO is used for.

Bit Bang SPI Description
DATA MOSI Master Out Slave In
LATCH SS Slave Select
CLOCK SCLK Serial Clock
- MISO Master In Slave Out

Before you can use SPI it must be configured. Main things to do are setting the device to work as master and the data order. Most of the time this is enough. Configuration is done by setting the appropriate bit in the SPI Control Register SPCR. For all configurable options see the Control and Status Registers table. When using SPI you cannot use any arbitrary pins. Instead read your datasheet to find out which pins your microcontroller uses for SPI. Values below are for ATmega32U4 which is used in both Adafruit ATmega32U4 Breakout Board and Teensy USB Development Board.

#define SS   B0
#define SCLK B1
#define MOSI B2
#define MISO B3

void spi_init(void) {
    pin_mode(SCLK, OUTPUT);
    pin_mode(MOSI, OUTPUT);
    pin_mode(SS, OUTPUT); /* Should be output in Master mode. */

    SPCR &= ~(_BV(DORD)); /* MSB first. */
    SPCR |= _BV(MSTR);    /* Act as master. */
    SPCR |= _BV(SPE);     /* Enable SPI. */
}

After SPI is configured reading and writing to it is easy. When byte is written to SPI Data Register SPDR it will be transmitted to slave. Received bytes (if any) are written to hardware receive buffer. Reading SPDR will return the data in receive buffer.

uint8_t spi_transfer(volatile uint8_t data) {
    SPDR = data;
    loop_until_bit_is_set(SPSR, SPIF);
    return SPDR;
}

Why spi_transfer() and not separate spi_read() and spi_write() functions? Internally both master and slave are 8-bit shift registers (do not confuse this with the TPIC6B595 shift register used in article). One bit is shifted from the master to the slave and from the slave to the master simultaneously in one serial clock cycle. After eight SLCK pulses data has been exchanged between master and slave. Slave never sends data to master by itself. Master always must write something to slave.

Main program is essentially the same as when using shift_out() function. Since we do not read anything back we can just ignore return value of spi_transfer() call.

int main(void) {

    spi_init();

    for(uint16_t i = 0; i < 0xffff; i++) {
        /* Shift high byte first to shift registers. */
        spi_transfer(i >> 8);
        spi_transfer(i & 0xff);

        /* Pulse latch to transfer data from shift registers */
        /* to storage registers. */
        digital_write(SPI_SS, LOW);
        digital_write(SPI_SS, HIGH);
    }

    return 0;
}

Control and Status Registers

SPCR Bit # Name Description
bit 7 SPIE SPI Interrupt Enable.
bit 6 SPE SPI Enable. When set hardware SPI operations will be enabled.
bit 5 DORD Data Order. When set LSB will be transmitted first.
bit 4 MSTR Master / Slave Select. When set device will act as SPI master.
bit 3 CPOL Clock Polarity. When set leading edge will be falling and trailing edge rising. Vice versa when unset.
bit 2 CPHA Clock Phase. When set data will be sampled on trailing edge of the clock. Vice versa when unset.
bit 1
bit 0
SPR1
SPR0
SPI Clock Rate Select 1 and 0. Used together with SPI2X to set the SCK frequency.
SPSR Bit # Name Description
bit 7 SPIF SPI Interrupt Flag. Set when a serial transfer is complete. An interrupt is generated if SPIE in SPCR is set and global interrupts are enabled. Cleared by hardware when interrupt handling vector is executed.
bit 6 WCOL Write Collision Flag. Set if the SPDR is written during a data transfer.
bit 5
bit 4
bit 3
bit 2
bit 1
Reserved. Always zero.
bit 0 SPI2X Double SPI Speed. Used together with SPR1 and SPR0 to set the SCK frequency.
SPI2X SPR1 SPR0 SCK Frequency
0 0 0 fosc/4
0 0 1 fosc/16
0 1 0 fosc/64
0 1 1 fosc/128
1 0 0 fosc/2
1 0 1 fosc/8
1 1 0 fosc/32
1 1 1 fosc/64

Wiring TPIC6B595

Wiring is pretty straight forward but depends on the chip used. TPIC6B595 from Adafruit was used when writing this article.

All shift registers should share CLOCK and LATCH signals. When cascading more than one shift register DATA is redirected to next register by connecting SER OUT to SER IN. Outputs are connected to corresponding leds. To enable outputs of TPIC6B595 you must also tie SRCLR pin to positive voltage and G pin to ground.

In image below CLOCK is blue, LATCH is yellow and DATA is orange.

More Reading

Full source code of this article. Introduction to 74HC595 Shift Register by ProtoStack. The 74HC595 8 bit shift register by DrLuke. Setup And Use of The SPI technote by Atmel. The Serial Peripheral Interface from AVR beginners. Serial Peripheral Interface Bus article in Wikipedia.



When asking a question please include an URL to example page where the problem occurs. If you have longer code examples please use pastie.org.
CATEGORIES
Built using the awesome Flat UI Pro framework by Designmodo.

© 2013 Mika Tuupola.