Issue driving a shift register

shift-register

I am trying to drive a 74ACT299 shift register with a Microcontroller. Looking at the datasheet I thought it was pretty simple. Set the data bit then pulse the clock, repeat. After I wrote the code, I set up a test circuit with on LED on each output. When I run to the code to light each led in order, I get some weird results. The LEDs generally light two at a time. They do so in increasing order, but something in a pattern like the following. I varies slightly each iteration.

loop 1: none
loop 2: none
loop 3: LED 1
loop 4: LED 1, 2
loop 5: LED 2, 3
loop 6: LED 3
loop 7: LED 4, 5
loop 8: LED 5, 6
etc...

I figured maybe my code wasn't shifting the bits out properly so I connected a logic analyser and it produced the following waveform.

Logic Analyser Wave Form

Each clock pulse is ~7.80 µs and the time between clock pulses is ~37.5 µs.

The circuit is setup as seen below. The Data, Clock, and Enable lines are being driver by an MSP430 at 3.3v.

schematic

simulate this circuit – Schematic created using CircuitLab

The code running on the MSP430 is listed below.

#include <msp430.h> 

#define OUTPUT_ENABLE BIT5
#define DATA BIT4
#define CLOCK BIT3

void shift_out(unsigned char data, unsigned char data_pin, unsigned char clock_pin);

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer

    P1DIR |= OUTPUT_ENABLE | DATA | CLOCK;

    // set everything low
    P1OUT &= 0xFF - (OUTPUT_ENABLE | DATA | CLOCK);

    int x;
    for (;;) {
        for (x = 0; x < 8; x++)
        {
            // Disable the outputs
            P1OUT |= OUTPUT_ENABLE;

            int out = 1 << x;
            shift_out(out, DATA, CLOCK);


            // Enable the outputs
            P1OUT &= 0xFF - OUTPUT_ENABLE;

            __delay_cycles(500000);
        }
    }
}

void shift_out(unsigned char data, unsigned char data_pin, unsigned char clock_pin)
{
    int i;
    for (i = 0; i < 8; i++)
    {
        // set data pin to value
        if ((1 << i) & data) {
            P1OUT |= data_pin;
        } else {
            P1OUT &= 0xFF - data_pin;
        }

        // clock high
        P1OUT |= clock_pin;

        // clock low
        P1OUT &= 0xFF - clock_pin;
    }
}

I have fought with this for a few days and can't find any errors. I assume I am either missing something about the shift register or something. I would be most appreciative if someone could point me in the right direction about where the error might be. I am at loss of where to look next.

Best Answer

The code and logic analyzer output looks okay. It would not hurt to put a NOP or two before driving the clock high.

The 74ACT299 is a pretty fast chip (100MHz clock at 5V). I'm guessing you're getting ground bounce between your SR and the driving circuit. This should be suspected especially if you have long wires between the two (make sure the ground wire as well as the signal wires are short and direct).

You should also have the 74ACT299 power supply bypassed close to the chip with 0.1uF to 1uF ceramic. This is non-optional in general, but especially when you're driving a lot of current into the LEDs. If all the LEDs switch at once you've got ~100mA flying around with nanosecond edges.