Problems with AD545x Multiplying DAC SPI Communication

I'm fairly new to Arduino (analog guy being dragged into the digital world), so I'm probably going to ask some dumb questions.

I'm trying to control an AD5450 Multiplying DAC using an Arduino Uno. The AD5450 uses an "SPI compatible" serial interface... which I'm quickly discovering isn't as simple as I thought it was. The datasheet can be found here:
https://www.analog.com/media/en/technical-documentation/data-sheets/AD5450_5451_5452_5453.pdf

Here's the test code I initially came up with. Ultimately this will be used as a programmable gain amplifier for the input section of an audio power amp. Unsurprisingly, if you read the datasheet, my function ad5450Write(bitlevel) won't work.

#include <SPI.h>
int slaveSelect = 10;
void setup() {
  pinMode(slaveSelect, OUTPUT);
  SPI.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  ad5450Write(255);
  delay(1000);
  ad5450Write(0);
  delay(1000);

void ad5450Write(int bitlevel){
  digitalWrite(slaveSelect, LOW);
  delay(10);
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
  SPI.transfer(bitlevel);
  SPI.endTransaction();
  delay(10);
  digitalWrite(slaveSelect, HIGH);
}

The main problem I am running into is that the AD545x series requires 16-bit words. The first two bits are control bits (in my case, I want both of them to be zero). Then comes (in the AD5450 case) 8 bits of data that set the level from 0-255. The rest of the bits (as I understand it) will be ignored.

I tried inserting SPI.transfer(0b00) before the SPI.transfer(bitlevel), but this did not work either. As I understand it, this is because SPI sends out 8-bit words. What I need is to send out 16 bit words, with the first two bits as zeros, my level, and then more zeros.

Can anyone give more some pointers on the best way to do this? I know I could do it with "bit-banging", however I'd really like to avoid doing so if I can.

Thanks in advance,

H713

that code was a good effort. if you look at page 21 of the datasheet its explains it quite clearly but I guess what was where the challenge was for you! :wink:

the trick is to shift the bits and split the 16 bits in to 2 bytes. so something like this in code:

(compiles, not tested!)

#include <SPI.h>
/*
  DAC Control Bits
  C1 C0 Function Implemented
  0 0   Load and update (power-on default)
  0 1   Reserved
  1 0   Reserved
  1 1   Clock data to shift register upon rising edge
*/

uint8_t slaveSelect = 10;

void ad5450Write(uint8_t bitlevel) {
  uint16_t data = bitlevel << 6;
  uint8_t *p_data = (uint8_t *) &data;
  uint8_t controlbits = 0x00; //0x00 Load and update
                              //0xC0 Clock data to shift register upon rising edge

  digitalWrite(slaveSelect, LOW);

  SPI.transfer(controlbits | p_data[1]); //send upper byte first
  SPI.transfer(p_data[0] | 0x3F); //send lower byte. Pad bits 0-5 with 1's

  digitalWrite(slaveSelect, HIGH);
}

void setup() {
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1));
  pinMode(slaveSelect, OUTPUT);
  digitalWrite(slaveSelect, HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:
  ad5450Write(255); //hex value = 0xFF
  delay(1000);
  ad5450Write(0);
  delay(1000);
}

hope that helps...