Codevision AVR SPI function question - 16 bits ??

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

I'm trying to send 16 bits of information (4 padding zero's and 12 real data bits) to a Maxim MAX531 DAC using Codevision AVR V2.03.5 along with a Mega32 running at 1Mhz with its internal RC clock.

Basically I had a for loop which runs from 0 to 4095, a couple of macros (found whilst lurking... courtesy of Mr Rogers on the Yahoo Codevision group - thanks!) which split the 16 bit count into hi and lo bytes which I then tried to send to my DAC using the SPI.

I was able to send the lo byte and make that set the DAC nicely but for some reason I can't get the DAC to load all 16 bits.

Using the simulator I can see that the hi / lo macros are working correctly.

I expected that I'd just be able to do something like this:

SS = 0;
junk = spi(hi_byte); //Send hi byte, read last
junk = spi(lo_byte); //Send lo byte, ditto

...but this only works for the first byte.

SPSR is set to 0xD0, and SPSR to 0x00.

I would post my code, but I have that many tryout versions I'm not sure which one is best to post.
Currently version control isn't one of my strong points. Must do better :oops:

Is what I'm doing reasonable - can the spi() routine do what I'm wanting or do I need to do this by bit banging ?

Thanks
Robin

PS I have spent some time searching the archives and the web for suitable clues but didn't find the answer - I found lots of posts which said that spi was fairly trivial to use, so I feel an even bigger dumbo now. :roll:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Instead of junking the return value, why not read it ?

You should get your previous byte back. Unless of course it is a device that specifically sends its data back.

This will tell you if your device is at least awake. Make sure that the device is receiving the SS = 0. You should have the DDR bits set accordingly.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

SPSR is set to 0xD0

Why are you setting SPIE with no ISR to catch it? [Well, we don't really know that but I know of no practical readson to use SPIE in a master SPI setup.]

Is the /SS pin configured as an output?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David / Lee, thanks for the quick reply.

No ISR ? Yes, you got me there...

Currently I have SS, MOSI and SCK set as outputs and set to 1 initially. I have MISO set as an input and have read back the bytes as they've been sent - then sent them (inverted) to Port A so the leds on the STK500 blink in sympathy.

I'll try again with SPIE sorted out and if that doesn't work I think I need to get a version going which half works then I'll post the code along with some scope plots.

Cheers again
Robin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Robbin
I drive the LTC1661 10 bit DAC from the SPI port, it has 2 channels and you send 16 bits to it selecting which channel to write to and what mode to use. The 10 bits become -
starting from MSbit- 4 bits mode and address, 10 bit data and 2 bits of don't care.

You're probably not that interested in the DAC detail but the SPI is very simple to use. What I do you can see from the last 4 lines, I drop the /CS line (called NDAC_CS), send the 2 bytes the raise the /CS line. I ignore the SS line, its just a general IO line when the Mega168 is SPI master anyway.

:
#define NDAC_CS  PORTB.2
:
:
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2*460.800 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x50;
SPSR=0x01;
:
:

// Write 10 bit value to DAC using the SPI port
void dac_write(char channel, unsigned int DAC_Tx_val)
{
     //Make up the data word that the DAC needs for both channels
     unsigned int ch_mask=0x9000;
     DAC_Tx_val &= 0x3FF;  // make sure there are no funnies
     if (channel) // DAC 1 or 2 ?
        {
        ch_mask= 0xA000;
        }
     DAC_Tx_val =(DAC_Tx_val << 2)| ch_mask ;
     NDAC_CS=0;
     spi(DAC_Tx_val>>8);
     spi(DAC_Tx_val);
     NDAC_CS=1;
}

I let the (wonderful) code wizard double check the port settings for me.

cheers
Klave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I ignore the SS line, its just a general IO line when the Mega168 is SPI master anyway.

Klave--Careful on that. When your AVR is configured as an SPI master, if the /SS is an input then it will change your AVR from master SPI to slave SPI if it "fires" and goes low. Thus, most of us will use it as the select line for the slave device, or otherwise allocate it to be an output.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Lee
I see that I had inadvertently used it as the chip select line, PORTB.2 but that was not because of the reason you mentioned, probably more because of some engineering "use things as they were intended or as near as possible" reason.

This is why I read the forum and the data sheet.

Cheers

Klave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Klave, thanks for that.

You've confirmed that it should work if I get the setup correct, so I'm not going nuts.

Have a virtual beer on me all you guys :D

Cheers
Robin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All sorted :D

I think it's fair to say that my understanding of the datasheet was somewhat lacking.... all now working nicely and as I'd expected.

Thanks again David, Lee & Klave.

Kind Regards,
Robin