demkat1:
Hello,
Im trying to program a DDS AD9833 signal generator module like this one :
Programmable Microprocessors Sine Square Wave Ad9833 DDS Signal Generator Module for sale online | eBay
The signal I want is 400Hz, sine.
Fortunately there is application note AN-1070 from Analog Devices, that explains the programming bytes. That is :
MORE ON PROGRAMMING THE AD9833/AD9834
A simple example is the best method to explain how to program the AD9833/ AD9834. Refer to the AD9833 or the AD9834 data sheet for more details.
Basic Example
The aim is to generate a 400 Hz output frequency using the AD9833 with a 25 MHz MCLK.
The dial-up code for this is defined by the equation MCLKOUTffFreqReg282×=
Thus, for this example, Freq 0 = 400 Hz.
= 4295 decimal = 0x10C7 = 0001 0000 1100 0111
The required initialization sequence is shown in Table 1.
Table 1.
Hexadecimal Binary
0x2100 0010 0001 0000 0000
0x50C7 0101 0000 1100 0111
0x4000 0100 0000 0000 0000
0xC000 1100 0000 0000 0000
0x2000 0010 0000 0000 0000
So, I made up the following code
#include <SPI.h>
const int csPin = 10;
void setup() {
SPI.begin();
SPI.setBitOrder(MSBFIRST);
pinMode(csPin, OUTPUT);
digitalWrite(csPin, HIGH);
delay(10);
byte a11 = 0x21;
byte a12 = 0x00;
byte a21 = 0x50;
byte a22 = 0xC7;
byte a31 = 0x40;
byte a32 = 0x00;
byte a41 = 0xC0;
byte a42 = 0x00;
byte a51 = 0x20;
byte a52 = 0x00;
word a1 = 0x2100;
word a2 = 0x50C7;
word a3 = 0x4000;
word a4 = 0xC000;
word a5 = 0x2000;
/*
sendit(a11, a12);
sendit(a21, a22);
sendit(a31, a32);
sendit(a41, a42);
sendit(a51, a52);
*/
senditword(a1);
senditword(a2);
senditword(a3);
senditword(a4);
senditword(a5);
}
void loop() {
// put your main code here, to run repeatedly:
}
void senditword(word b1) {
// remember mode and cpha and pol
digitalWrite(csPin, LOW); //select slave
SPI.transfer(b1);
delay(1);
digitalWrite(csPin, HIGH); //de-select slave
delay(1);
}
/*
void sendit(byte byte1, byte byte2) {
digitalWrite(csPin, LOW); //select slave
SPI.transfer(byte1);
SPI.transfer(byte2);
digitalWrite(csPin, HIGH); //de-select slave
delay(1);
}
*/
As you see, I tried in 2 ways :
1, send 10 bytes
2, send 5 words
But no way was succwesfull. In all cases the module seems to go erratically to a "random" frequency.
Any ideas?
thank you
I came on the same problem weeks ago and i found a working routine from web, i test it with a Nano board and a scope. works like a charm
/*
AD9833 Waveform Module vwlowen.co.uk
*/
#include <SPI.h>
const int SINE = 0x2000; // Define AD9833's waveform register value.
const int SQUARE = 0x2028; // When we update the frequency, we need to
const int TRIANGLE = 0x2002; // define the waveform when we end writing.
int wave = 0;
int waveType = SINE;
int wavePin = 7;
const float refFreq = 25000000.0; // On-board crystal reference frequency
const int FSYNC = 10; // Standard SPI pins for the AD9833 waveform generator.
const int CLK = 13; // CLK and DATA pins are shared with the TFT display.
const int DATA = 11;
unsigned long freq = 640; // Set initial frequency.
void setup() {
// Can't set SPI MODE here because the display and the AD9833 use different MODES.
SPI.begin();
AD9833reset(); // Reset AD9833 module after power-up.
delay(50);
AD9833setFrequency(freq, SQUARE); // Set the frequency and Sine Wave output
}
void loop() {
}
// AD9833 documentation advises a 'Reset' on first applying power.
void AD9833reset() {
WriteRegister(0x100); // Write '1' to AD9833 Control register bit D8.
delay(10);
}
// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(long frequency, int Waveform) {
long FreqWord = (frequency * pow(2, 28)) / refFreq;
int MSB = (int)((FreqWord & 0xFFFC000) >> 14); //Only lower 14 bits are used for data
int LSB = (int)(FreqWord & 0x3FFF);
//Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0
LSB |= 0x4000;
MSB |= 0x4000;
WriteRegister(0x2100);
WriteRegister(LSB); // Write lower 16 bits to AD9833 registers
WriteRegister(MSB); // Write upper 16 bits to AD9833 registers.
WriteRegister(0xC000); // Phase register
WriteRegister(Waveform); // Exit & Reset to SINE, SQUARE or TRIANGLE
}
void WriteRegister(int dat) {
// Display and AD9833 use different SPI MODES so it has to be set for the AD9833 here.
SPI.setDataMode(SPI_MODE2);
digitalWrite(FSYNC, LOW); // Set FSYNC low before writing to AD9833 registers
delayMicroseconds(10); // Give AD9833 time to get ready to receive data.
SPI.transfer(highByte(dat)); // Each AD9833 register is 32 bits wide and each 16
SPI.transfer(lowByte(dat)); // bits has to be transferred as 2 x 8-bit bytes.
digitalWrite(FSYNC, HIGH); //Write done. Set FSYNC high
}