AD9833 Problems with Arduino and SPI [Can't think of a good title]
Summary

It appears to be working fine as-designed.

If you want us to further debug this problem, you need to explicitly say (1) what you expected to see, (2) what you actually saw, and (3) what appears to be the difference.

Some of the hardest problems for me to debug are when I'm convinced there is a problem with something, but it turns out that everything is actually working just fine -- I'm mis-interpreting what I see on my o'scope as a problem, when actually my o'scope is showing me that things are working fine.

Also: good job reducing your code to a relatively short SSCCE.
That made it much easier to figure out what was going on.
Thanks.

details

This image is exactly what I expect to see on the scope when the DAC in a DDS is programmed to generate a sine wave close to (but not exactly the same as) 1/5 the output sample rate.



It doesn't matter how many bits of resolution the DAC has, if you only have time to output 5 sample values per cycle of the sinewave, you're going to see 5 steps per cycle of the output waveform, as you see here.

This is perfectly normal and expected.
All the so-called "sine-wave" DTMF generators I've used have very similar-looking outputs.

With some applications (such as the DTMF generators I've used), while such waveforms may look pretty ugly on the o'scope and not even recognizable as sine waves, they work perfectly fine in practice.

With many applications, a little bit of filtering rounds off the sharp stair-step edges so it looks like a sine wave on the o-scope. (A series RC filter circuit is often adequate).

A few applications are very sensitive to harmonic and non-harmonic distortion caused by this sort of stair-steps.
With such applications, you must either
(a) heavily filter the output to get rid of the sample-rate frequency and all its harmonics, or
(b) increase the sample rate to get it out of the sensitive zone.
In your case, you may be able to bump your master clock up to 12.5 MHz fairly easily, but above that requires more serious hardware modifications.
(People who do RF often can't do (b) and so are forced to use option (a) and spend a lot of time carefully tuning complex RLC ladder filters and worrying about component value drift.
People who do audio electronics often find option (b) a lot simpler.
)

If I understand your code correctly, you're writing 0x30FF to the 14 MSB of the 28-bit FREQ0 register.
While normally increasing the binary value in the FREQ register increases the output frequency,
frequency aliasing / undersampling  / Nyquist rate effects
cause values over half the period (in this case, values over 0x2000 in the 14 MSB) to alias and appear to generate a lower frequency.
(Such values are still useful when generating triangle waves ...)
So I expect the same frequency as 0x4000 - 0x30FF = 0x0F01.

output_frequency = Phase * f_MCLK /( 2^28 )  # (from p. 12 of datasheet)


In this case, Phase is effectively (0x0F01&lt;&lt;14), giving an output frequency with only about (2^28 / (0x0F01&lt;&lt;14)) == 4.2 samples per output cycle.
At f_MCLK == 1 MHz, I expect an output frequency of about 230 KHz, which is about what I see on your scope.

If you really need to generate a frequency of more than half of 1 MHz, you need to change your hardware.

EDIT:


  By my calculations the FREQ register should have 0x30FFC0F = 51.379E6.


I wish this chip were designed such that that were true.
But because this chip uses funky 14-bit register loads,

SPI.transfer(0x4C);     //write 0x0C0F to 14LSB
...
SPI.transfer(0x70);     //write 0x30FF to 14MSB


ends up putting (0x30FF)&lt;&lt;14 + 0x0C0F == (0x30FF)*2^14 + 0x0C0F == 0x0C3F_CC0F == 206e6 (decimal) into the FREQ0 register.
Because this is more than half of 2^28, we see aliasing foldback,
so the output frequency is the same as loading 0x1000_000 - 0x0C3F_CC0F = 0x03C033F1 into the FREQ0 register.
Since 2^28 / 0x03C033F1 is about 4.3, you'll see 4 or 5 steps per complete "sine wave".
And with 1 MHz step rate, that gives an output frequency of about 0x03C033F1 * 1 MHz / 2^28 which is about 230 kHz.

I think you want something more like

// FIXME: do this without float, only integers,
// without overflowing the 32-bit Arduino "long int" ?
void set_frequency( long int desired_frequency ){
    const long int f_MCLK = 1e6; // change to 10e6 when we put the 10 MHz crystal in.
    ASSERT( (desired_frequency * 2) &lt; f_MCLK );
    const int phase0command = 0x4000;
    const float steps_per_Hz = (1.0 * ((long int)1)&lt;&lt;28) / f_MCLK;
    // phase =  (desired_frequency * 2^28) / f_MCLK
    unsigned long int steps_per_clk = desired_frequency * steps_per_Hz;
    unsigned int high14 = steps_per_clk &gt;&gt; 14;
    unsigned int low14 = steps_per_clk &amp; (0x3FFF);
    digitalWrite(fSync, LOW);
    SPI.transfer16(phase0command | low14);
    digitalWrite(fSync, HIGH);
    delayMicroseconds(1);
    digitalWrite(fSync, LOW);
    SPI.transfer16(phase0command | high14);
    digitalWrite(fSync, HIGH);
}