Go Down

Topic: Hardware SPI on 74HC595N - Stumped (Read 6071 times) previous topic - next topic

spirilis

So I have a 74HC595N from Sparkfun, and I'm trying to get it working with my old Arduino NG w/ ATmega8.

I have it working with a bit-bang interface, hooked up pins 2-6 to all the SER-through-SRCLR pins and got it working there.  Didn't need to have SRCLR and OE hooked up to the arduino, connecting to Vcc and GND worked fine and that's how I have it set up with the SPI configuration.
(datasheet for reference: http://www.sparkfun.com/datasheets/IC/SN74HC595.pdf)

But using the SPI library, and even trying a manual run of the hardware SPI interface (found here: http://softsolder.com/2009/07/18/arduino-hardware-assisted-spi-synchronous-serial-data-io/) does not work at all.  I keep writing B10101010 to it and all the output pins end up sunk to GND.  For kicks I connected MISO to the QH' pin on the shift register and wrote the byte twice to see if I got the first copy of the byte returned, but it was all zeroes.

Current wiring:
Arduino pin 13 -> SRCLK
Arduino pin 12 -> QH'
Arduino pin 11 -> SER
Arduino pin 10 -> Empty
Arduino pin 9 -> RCLK

Pic of breadboard: http://spirilis.net/junk/dsc_4335.jpg (warning- large JPEG!)

Environment:  Arduino IDE 0022 running on MacOSX 10.6

Code:
Code: [Select]

#include <SPI.h>

#define myLatchPin 9

void setup() {
  Serial.begin(9600);

  pinMode(myLatchPin, OUTPUT);
  digitalWrite(myLatchPin, HIGH);
  pinMode(10,OUTPUT);  // SPI.begin() should cover this, but just in case...
  digitalWrite(10,HIGH);
 
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
}

void loop() {
  byte ret;
  Serial.println("Writing 10101010");
  digitalWrite(myLatchPin,LOW);

  ret = SPI.transfer(B10101010); 
  ret = SPI.transfer(B10101010);

  digitalWrite(myLatchPin,HIGH);

  Serial.println(ret, BIN);
  Serial.println("Done; looping forever");
  SPI.end();
  while (1) {
    delay(2000);
  }
}


I tried SPI_CLOCK_DIV128 and DIV8 for kicks, no difference.

Rather stumped at this point.  Any ideas?

CrossRoads

try a simple

SPI.transfer(your_data);

to send the date out.   

What does the "ret= ..." do?
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

spirilis

#2
May 06, 2011, 12:17 pm Last Edit: May 06, 2011, 12:19 pm by spirilis Reason: 1
ret= just gets the return value in case there's anything relevant.

Tried this, still no go:

Code: [Select]

#include <SPI.h>

#define myLatchPin 9

void setup() {
 pinMode(myLatchPin, OUTPUT);
 SPI.begin();
}

void loop() {
 digitalWrite(myLatchPin, LOW);
 SPI.transfer(B10101010);
 digitalWrite(myLatchPin, HIGH);
 while(1) {
   delay(2000);
 }
}


The shift register remained in a power-on state which looked more like "00111111", then I manually cleared it (brought SRCLR low, then removed RCLK's wire and jumped it low) and reset the board, gave it 10 seconds or so to boot and still no intended effect.  All zeroes at that point (so it hadn't changed at all from the reset).

spirilis

OK, getting closer... Something about these pins is messed up.  Tried a simple bit bang on these same pins to no avail:
Code: [Select]

#define myLatchPin 9
#define myDataPin 11
#define myClockPin 13

void setup() {
  pinMode(myLatchPin,OUTPUT);
  pinMode(myDataPin,OUTPUT);
  pinMode(myClockPin,OUTPUT);
  digitalWrite(myClockPin, LOW);
}

void loop() {
  digitalWrite(myLatchPin, LOW);
  // Write 10101010
  digitalWrite(myDataPin, HIGH);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myDataPin, LOW);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myDataPin, HIGH);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myDataPin, LOW);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myDataPin, HIGH);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myDataPin, LOW);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myDataPin, HIGH);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myDataPin, LOW);
  digitalWrite(myClockPin, HIGH);
  digitalWrite(myClockPin, LOW);

  digitalWrite(myLatchPin, HIGH);

  while(1) {
    delay(2000);
  }
}


Worked fine using pins in the 2-6 range earlier.  I have a few other ATmega8's but they don't have the bootloader installed (and I have a brand new AVR-ISP500 mkII, but MacOSX doesn't like it right out of the box... trying to get Xcode installed so I can compile the libusb-bound avrdude, but Apple's website is experiencing "technical difficulties" at the moment when I try to register my acct lol)

spirilis

Moved the clock pin from pin 13 to pin 12, worked perfectly.  Huh, guess it doesn't like pin 13?  (or that LED attached to it really mucks things up??)

JChristensen

#5
May 06, 2011, 12:40 pm Last Edit: May 06, 2011, 12:43 pm by Jack Christensen Reason: 1

Moved the clock pin from pin 13 to pin 12, worked perfectly.  Huh, guess it doesn't like pin 13?  (or that LED attached to it really mucks things up??)


It certainly shouldn't.  SPI devices that use pin 13 (PB5) as SCK are too numerous to mention.

spirilis

Well sometimes it works, sometimes it doesn't.  Weird.  Playing around with it some more... I might have to make a serial input loop that writes integers so I can test it better.  Maybe tonight!

spirilis

Ah you know what, it just occurred to me that I don't have any load on the outputs--no pulldown resistors or LEDs.  Later I'll try attaching pulldown resistors to each of those (would use LEDs but, can't find my stash!)

johnwasser

Shift register pins:
SER (Serial Data In)
SRCLK (Shift Register Clock)
/SRCLR  (Shift Register Clear, Active Low)
RCLK (Register Clock)
/OE (Output Enable, Active Low)

Arduino SPI pins:
10 = /SS  (Slave Select, Active Low)
11 = MOSI (Master Out, Slave In)
12 = MISO (Master In, Slave Out)
13 = SCK (Serial Clock)

I would connect them this way:

/OE -> Ground
SER (Serial Data In) -> 11 (MOSI)
SRCLK (Shift Register Clock) -> 13 (SCK)
/SRCLR -> +5v
RCLK (Register Clock) -> 10 (/SS)

Be sure to set /SS LOW before the transfer and HIGH after.  The change to HIGH will latch the data into the output register.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

MarkT

You need a decoupling capacitor close to the shift register.  No logic chip is guaranteed to work without supply decoupling.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

spirilis

I think I narrowed it down.  Probing the voltage on pin 13 vs. ground when it is high, it's around 1.9V.  Testing pins 0 and 1, for instance, show a full 5V.

The voltage is 5V when probing pin 19 on the chip itself, so something must be amuck with my Arduino NG circuit board...
Also see 1.9V when probing one side of the LED for pin 19.
(tried another ATmega8 for kicks, burned the bootloader on it and uploaded my simple pin-turnon prog, still 1.9VDC at pin 13)

Oddly enough the bootloader worked fine, although I just checked the ICSP header -- pin 3 shows full 5VDC (I think that's the SCK pin) so I'm still betting I burned out something on the arduino circuit board.

spirilis

#11
May 07, 2011, 04:15 am Last Edit: May 07, 2011, 04:31 am by spirilis Reason: 1
Just wedged the SCK wire from the shift register to pin 19 on the ATmega8 chip (held in place by spring tension in the wire LOL) and it's working perfectly now.  With a double-write like this:
Code: [Select]

ret = SPI.transfer(B10101010);
ret = SPI.transfer(B10101010);


the return value prints out as "10101010" in binary, indicating that it successfully wrote the register both times (and got the first byte's contents back on the 2nd write).

Bravo!  Now to find a new board . . . (or consider soldering a jumper wire between the IC socket and the pin header)

johnwasser


I think I narrowed it down.  Probing the voltage on pin 13 vs. ground when it is high, it's around 1.9V.  Testing pins 0 and 1, for instance, show a full 5V.

The voltage is 5V when probing pin 19 on the chip itself, so something must be amuck with my Arduino NG circuit board...
Also see 1.9V when probing one side of the LED for pin 19.


http://www.arduino.cc/en/uploads/Main/arduino_NG_schematic.png

Looks like the NG has not one but TWO dropping resistors (470 ohm each) between the ATmega and Pin 13!  Every newer model from my Diecimila on up has Pin 13 connected directly to the chip and the resistor and LED hanging off that line.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

spirilis

#13
May 07, 2011, 02:22 pm Last Edit: May 07, 2011, 02:25 pm by spirilis Reason: 1
Good catch!  I'm going to solder a jumper wire there.

I am not sure how accurate my analog multimeter is with regards to resistance (seems to be spot-on with the voltmeter), but I measured around 15Kohms between the chip and the pin, so one of those resistors may have burned out or gone bad somehow...

spirilis

#14
May 07, 2011, 05:28 pm Last Edit: May 07, 2011, 05:31 pm by spirilis Reason: 1
Just soldered the jumper wire and set up a breadboard with 2 shift registers driving a 10-segment bar graph (http://www.sparkfun.com/products/9938)

After debugging some silly code mistakes I can enter a 16-bit word over the serial connection and have it apply correctly (and get the correct prior-value out of the 2nd shift register's QH' pin), and right now I'm running a much shorter app that alternates 5 lit LEDs back and forth every 250ms which makes for a nice visual display.  I tried it with no delay (and SPI_CLOCK_DIV2, so the HW SPI is running its fastest) but maintaining a counter and it was pushing over 35,000 updates/sec, probably gated by the serial I/O that was happening every second (moving to SPI_CLOCK_DIV4 registered 31,000 updates/sec, for comparison).  That or maybe the digitalWrite() statements for the latch pin was slowing it down.

Looks like I'm all set!  Thank you all for your help and suggestions.

Go Up