SPI Works.... sometimes?

So, I’m trying to interface my Arduino with a Maxim MAX5250 DAC. The forum software won’t let me link to the datasheet, but it’s easy to find at maxim-ic dot com.

I’ve done some coding, which is exhibiting strange behavior. It changes the voltage maybe 1 out of 4 times I reload the software.

Here’s the code, pretty standard so far:

#define DATAOUT 11
#define DATAIN 12
#define SPICLOCK 13
#define SLAVESELECT 10

byte tmpOne = B00111100;
byte tmpTwo = B00100100;
byte clr;
void setup(){

pinMode(SLAVESELECT, OUTPUT);
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK, OUTPUT);

digitalWrite(SLAVESELECT, HIGH);
digitalWrite(DATAOUT, LOW);
digitalWrite(SPICLOCK, LOW);
delay(500);
SPCR = B01010111;
clr=SPSR;
clr=SPDR;
delay(500);

}

void loop(){

// SPCR = B01010101;
clr=SPSR;
clr=SPDR;

//PORTB = B00000000;
digitalWrite(SLAVESELECT, LOW); // select the chip
spi_transfer(tmpOne);
spi_transfer(tmpTwo);
//PORTB = B00100000;
digitalWrite(SLAVESELECT, HIGH);
}

char spi_transfer(byte data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{
};
return SPDR; // return the received byte
}

Wondering if anyone has some thoughts as to why it’s not working correctly all of the time? I’m assuming it’s a timing issue somewhere, but I can’t narrow it down yet.

Thanks!

Check that you have sufficient delay. Or try adding a delay(100) in the loop function to test.

Make sure the chip has adequate decoupling:- http://www.thebox.myzen.co.uk/Tutorial/De-coupling.html

In setup, I would move "digitalWrite(SLAVESELECT, HIGH)" to before you configure the slave select pin for output. Otherwise it will be active low while you confgure clock and data pins.

Also, I would move the test away from the loop to run it only once from setup. As it is now, you keep setting the same value repeatedly at full speed with a very short timegap between slave select high and low.

Thanks everyone for the replies. I've tried the suggestions here, and haven't noticed significant improvement...

Re: adding a delay, I've tried delays of various lengths at different points in the program, and it actually seems to make things worse for some reason. Particularly when the delay is in the loop().

I've already decoupled the chip, using a 4.7uF cap in parallel with a 0.1uF - as specified in the MAX5250 datasheet. Do those values seem adequate? The link posted indicates that 47uF is a much more common value.

And finally, though moving the digitalWrite(SLAVESELECT, HIGH) call does make sense, it didn't have any notable effect on the behavior.

Would it help to have a schematic of pin connections to the chip?

EDIT: Also, I feel I should specify because it seems like it might be important. The DAC output changes only approx. 1 out of 4 times that the software is actually recompiled and reloaded to the Arduino. Manually resetting the Arduino has no effect.

I assume you are talking local decoupling for the DAC not bulk filtering at the power supply. The DAC does not draw much current when switching. You do not need a 47uF cap at the DAC. The 0.1uF cap should be placed very close to the DAC and have very short leads.

I am bot sure the differences between the MAX5250 and the TLV56xx parts but maybe my schematics or software examples could help. I am using the TLV5620 (4ch/8bit) on my NB1A board and a TLV5618A (2ch/12bit) on my NB2AS board. Schematics, layout and BOM information is in the datasheet for each board. Also on the site is a DAC and SPI library. The NB1A information is at http://wiblocks.luciani.org/NB1/NB1A-index.html The NB2AS information is at http://wiblocks.luciani.org/NB2/NB2AS-index.html

(* jcl *)


www: http://www.wiblocks.com twitter: http://twitter.com/wiblocks blog: http://luciani.org

When configuring SPI, you enable the SHPA bit (SPCR register). This determines whether data leads or trails the CLK pulse. Have you verified against the datasheet that this is correct?

jluciani - thanks for the links. It looks like a cool project, I'll take a closer look at it tonight. Curious, why did you go with an 8-bit DAC?

BenF - It looks like you may have spotted a problem. I'll try it the other way when I get home, and report back.

Thanks!

Okay - so, changing the SHPA bit seems to work. I also discovered I had the software shutdown enable pin pulled high, instead of low.

Thanks!

There are symbolic constants defined for all these register bits and using them make reading the code easier (especially after a few weeks if you need to go back and start wonder - what the h.. is this).

 // instead of this
 //SPCR = B01010011;
 // you could use this
 SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);

Good to see yoiu sorted it out - then it's back to business.

Thanks, that’s a cool tip. Where can I the reference for that?

jluciani - thanks for the links. It looks like a cool project, I'll take a closer look at it tonight. Curious, why did you go with an 8-bit DAC?

For the NB1A I went with a quad 8-bit DAC for cost. The few uCs that have DACs typically have an 8 or 10bit resolution. The 8 bit DAC and matching reference do not add too much to the cost.

For the NB2AS (644, RTC, uSD, DAC) I went with a dual 12-bit DAC. The DAC and matching reference add about $10 to the cost of the kit.

(* jcl *)