SPI.transfer of a 4bit and 12bit value as 2x 8bits?

I'm trying to control a AD5449 DAC and having some trouble working out how to set a 4bit register and a 12bit register via SPI:

I've tried this, but it doesn't work:


I'm guessing because the datasheet says "Data is written to the device in 16-bit words. Each 16-bit word consists of four control bits and 12 data bits" and the Arduino does SPI.transfer in 8bit words?

If split the two values across two SPI.transfers, where "0001" is the ctrl_bits and "111111111111" is the data_bits, it works:


The problem is that ctrl_bits and data_bits vary and I'm not sure how to concatenate these two variables and then split them in to two 8bit integers.

Is there a simple way of doing this? Am I missing something? Examples like this make it look simple but perhaps my device doesn't work that way.

Is there a simple way of doing this?

There are several ways. Each involves bit shifting. The bitRead(), bitSet(), and bitWrite() macros hide all that icky stuff from you.

Thanks Paul!

I’m not sure it’s the most elegant way but I achieved what I wanted. I’ll detail it here so others can find it via Google or via the forum search…

I needed to send the AD5449 DAC a 4bit integer (control register bits, called “ctrl_reg”) and a 12bit integer (the actual value to set the DAC R2R ladder, called “level”). This is tricky because the DAC wants a 16bit word so these two values need to be split and sent as two 8bit words (called byte1 and byte2 below)

// Example values
int ctrl_reg = 1; // 0001
int level = 3768; // 111010111000

// Shift 'ctrl_reg' left by 4 bits
int shifted_ctrl_reg = ctrl_reg << 4; // 00010000

// Shift 'level' 8 bits to the right
int shifted_right_level = level >> 8; // 00001110

// Create byte 1 by doing a bitwise or of 'shifted_ctrl_reg' and 'shifted_right_level'
int byte1 = shifted_ctrl_reg;
byte1 = byte1 | shifted_right_level; // 00011110

// Now in byte2 I only want the last 8 bits of 'level' as the first 4 were in byte1 so I just delete the first 4 bits from 'level' by making them 0
int byte2 = level;
bitWrite(byte2, 8, 0);
bitWrite(byte2, 9, 0);
bitWrite(byte2, 10, 0);
bitWrite(byte2, 11, 0);

// All done
SPI.transfer(byte1); // 00011110 = 'ctrl_reg' (0001) with first 4 bits of 'level' (1110)
SPI.transfer(byte2); // 10111000 = last 8 bits of 'level'

I also found this article helpful: http://www.reigndesign.com/blog/controlling-a-10-bit-digital-potentiometer-via-spi-with-arduino/

I now see that this thread is top of the Google search results for the terms I was using when trying to work this out so I hope this helps someone else!