Prior to testing this DAC, I tested two other DACs ....
I hate to repeat myself but
What voltage(s) are you applying to REF1 and REF2 on the DAC?
Now, sometimes I ask questions out of idle curiosity, but in this case I actually had a reason.
The reason that I asked is that for proper operation of this particular device, the maximum value of reference voltage is VDD-1.5 Volts. So: If you are applying 5 Volts to VDD and 3.3 Volts to REF1,REF2, it will be operating within spec.
But the full-scale voltage of the DAC will be Vref (minus 1 lsb) not 5 Volts. If you apply 3.3 Volts to VDD, then you should not put 5 Volt logic signals (SPI Clock and SPI MOSI) to the device. Furthermore, if you use 3.3 Volts VDD, then the reference voltage(s) should be no more than 1.8 Volts.
Here's my take on it: For most convenient use with a 5-Volt Arduino, apply 5 Volts to VDD and 3.3 Volts to Vref on the DAC.
...I had thought the SPI problem has been taken of.
I think that SPI can work and, in fact your values are monotonically increasing as you increment the DAC code byte, so it is (probably) OK. I, personally wouldn't even have thought of using SPI (I would just have waded in and done it the "hard way" with bit banging), but I can't see why SPI can't work for this.
Have you tried the experiment that I suggested: Put a single DAC code byte and read the voltage with a meter? Output voltage should be equal to
(Reference Voltage) * (DAC code word) / 256
Apply 5 Volts to VDD and 3.3 Volts to REF1 and REF2. Write 128 to the DAC. Read the voltage with a meter. Should be 1.65 Volts, right?
Now, read the voltage with Arduino analogRead. The ADC reading should be something like 338.
Anyhow convert the ADC reading to a voltage with something like this:
const float aRef = 5.0; // Make this value equal to the Arduino VCC (nominally 5 Volts but could be off by a percent or two).
. // write 128 to DAC
int adcValue = analogRead(0); // Or whatever channel you use
float adcVoltage = adcValue * aRef / 1024.0;
Serial.print("Analog reading = ");Serial.print(adcValue);
Serial.print(" => ");Serial.print(adcVoltage);
Bottom line: If the full-scale 8-bit DAC voltage is equal to the full-scale 10-bit ADC voltage, then you can divide the ADC reading by 4 and it should just about match the DAC code word. That's not the case for this particular DAC and your Arduino. There is also a factor of (DAC Reference)/(ADC Reference) But---See Footnote.
You could, in fact, use 3.3 Volts for the Arduino ADC reference by applying 3.3 Volts to the Arduino Aref input and changing the software to use the external reference. In fact, for best precision in any ADC operation, it's usually a Good Idea to use a reference voltage that is somewhere in the neighborhood of the maximum expected input voltage. At any rate, the formula for converting analogRead value to voltage is what I show above. Just change the aRef value to whatever you decide to use.