Arduino SPI Questions

I am interfacing my arduino with a 12 bit digital to analog converter (DAC). My DAC requires 4 bits of setup code, then 12 bits containing the value from 0 to 4095.

My question is using the spi_transfer code can I send just the 4 bits, then the 12 bits? I am having trouble getting this to work with more than 2 spi_transfers at one time. Here is that portion of my code:

void loop() { // write_pot(3000, B0110); // delay(1000); // write_pot(3500, B0110); // delay(1000); digitalWrite(SLAVESELECT,LOW); spi_transfer(B00011111); spi_transfer(B11111111);

digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer digitalWrite(LDAC, LOW); // signals chip to accept transfer digitalWrite(LDAC, HIGH);

delay(1000);

digitalWrite(SLAVESELECT,LOW); spi_transfer(B00010000); spi_transfer(B00000000); digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer digitalWrite(LDAC, LOW); // signals chip to accept transfer digitalWrite(LDAC, HIGH);

delay(1000); }

Right now this blinks the DAC output from 4.0V to 0 V every 1 second. This is just for testing purposes of course. What I want to do is somehow separate the 4 bit setup info from the 12 bit data.

I have tried the following to no success:

void loop() { // write_pot(3000, B0110); // delay(1000); // write_pot(3500, B0110); // delay(1000); digitalWrite(SLAVESELECT,LOW); spi_transfer(B0001);// DAC setup 4 bits spi_transfer(B1111); spi_transfer(B11111111);

digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer digitalWrite(LDAC, LOW); // signals chip to accept transfer digitalWrite(LDAC, HIGH);

delay(1000);

digitalWrite(SLAVESELECT,LOW); spi_transfer(B00010000); spi_transfer(B00000000); digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer digitalWrite(LDAC, LOW); // signals chip to accept transfer digitalWrite(LDAC, HIGH);

delay(1000); }

Please let me know if you have any suggestions!

This might be a silly question, but why do you need to send the 4 bits separately? Can you just build the byte with bit arithmetic first, then send it?

Perhaps we could give you a better help if you give the reference of the DAC you are using

This might be a silly question, but why do you need to send the 4 bits separately? Can you just build the byte with bit arithmetic first, then send it?


So, that may be a silly question, but not to me! I did just that and it works right. I am very new to this and just figured out bit math yesterday. So, yeah, it works now. The DAC that I am using is the MCP4821 from digikey.

Here is my code that works:

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK 13//sck
#define SLAVESELECT 10//ss
#define LDAC 9 // ldac

// for o-scope

#define ANALOG_IN 0

#define joyPin 1

byte pot=0;
byte resistance=0;

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

void setup()
{
byte i;
byte clr;
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);
pinMode(LDAC, OUTPUT);
digitalWrite(SLAVESELECT,HIGH); //disable device
digitalWrite(LDAC, HIGH);
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 (fastest)
SPCR = (0<<SPIE)|(1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPHA);
clr=SPSR;
clr=SPDR;
delay(10);

Serial.begin(9600);

}

void loop()
{

int analogIn = analogRead(joyPin);
byte highByte = 0;
int data = 4*analogIn;
byte dataHigh = data >> 8;
byte DACsetup = B00010000;
if (data > 255){
highByte = DACsetup | dataHigh;}
else if (data <= 255){
highByte = DACsetup;}
byte lowByte = data;

// SPI to DAC writing value of DATA above

digitalWrite(SLAVESELECT,LOW);
spi_transfer(highByte);
spi_transfer(lowByte);
digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
digitalWrite(LDAC, LOW); // signals chip to accept transfer
digitalWrite(LDAC, HIGH);
int val = analogRead(ANALOG_IN);
Serial.print( 0xff, BYTE);
Serial.print( (val >> 8) & 0xff, BYTE);
Serial.print( val & 0xff, BYTE);
delay(1);

/*
delay(1000);

digitalWrite(SLAVESELECT,LOW);
spi_transfer(B00010000);
spi_transfer(B00000000);
digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
digitalWrite(LDAC, LOW); // signals chip to accept transfer
digitalWrite(LDAC, HIGH);

delay(1000);
*/
}

I lost track of your project right after I suggested you use the MCP4821. I see you've been having quite a time but it looks like you've got it going now.

The LDAC control is most useful when you are using the MCP4822 dual DAC version of this part and is used to synchronize the update of the two DACs. If you tie it LOW the DAC will update on driving /CS (SS) high and save you an output pin if you want to try that.

I will try tying the LDAC pin low and see what happens.

Thanks again, Ryan

Are you sure that spitransfer will transfer four bits at a time? If it only transfers bytes you are sending four unkown bits every time you sent the setup data.

(* jcl *)