There has been an error in the AD9951 data sheet which leads to some confusion about byte order when reading or writing registers. Analog Devices is correcting this error in the next revision of the data sheet. I have a tested and working set of routines based on the procedures written earlier in this post by Andy Kirkham.
/***************
Copied and modified from discussion forum but the basic code was
originally done by Andy Kirkham
Andy Kirkham's proviso below ......
Note, I don't have an AD9951 so this is untested experimental code.
It compiles but I have no idea if it actually works. It's purely demo code.
I started working on this circa 20 April, 2015 for use in my
Return Loss bridge.
The order of the bytes sent or received is, in the AD9951 data sheet,
the opposite of what actually works. That is to say, there is a conflict
between the description and the example given in the next paragraph.
I gather from the Web, everyone assumes most-significant bytes first.!
Jim Koehler, VE5FP
Comox, October, 2015
Routines work correctly, December, 2015
***************/
- ifndef AD9951_H
- define AD9951_H
- include "mbed.h"
- include "definitions.h"
the definitions.h file contains the definitons of 'multiplier' and ClockFrequency'
used in these procedures
class AD9951
{
protected:
SPI _spi;
DigitalOut _cs;
DigitalOut _rst;
DigitalOut _iou;
public:
AD9951(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName io_update) :
_spi(mosi, miso, sclk), _cs(cs), _rst(rst), _iou(io_update) {
_spi.format(8, 0);
_spi.frequency(1000000);
_cs.write(0);
_rst.write(1);
wait(0.01);
_rst.write(0);
_cs.write(1); deselect the AD9951 ... it is again selected in each of the procedures and functions
};
void Pulse_IO_Update(void) {
_iou.write(1);
wait_us(25);
_iou.write(0);
}
Write a 32bit register at the specified address.
void write_reg_4byte(int address, uint32_t value) {
_cs.write(0);
wait_us(10);
_spi.write(address);
_spi.write((value >> 24) & 0xFF);
_spi.write((value >> 16) & 0xFF);
_spi.write((value >> 8) & 0xFF);
_spi.write(value & 0xFF);
wait_us(10);
Pulse_IO_Update();
wait_us(10);
_cs.write(1);
}
Write a 24bit register at the specified address.
void write_reg_3byte(int address, uint32_t value) {
_cs.write(0);
wait_us(10);
_spi.write(address);
_spi.write((value >> 16) & 0xFF);
_spi.write((value >> 8) & 0xFF);
_spi.write(value & 0xFF);
wait_us(10);
Pulse_IO_Update();
wait_us(10);
_cs.write(1);
}
Write a 16bit register at the specified address.
void write_reg_2byte(int address, uint32_t value) {
_cs.write(0);
wait_us(10);
_spi.write(address);
_spi.write((value >> 8) & 0xFF);
_spi.write(value & 0xFF);
wait_us(10);
Pulse_IO_Update();
wait_us(10);
_cs.write(1);
}
Write a 8bit register at the specified address.
void write_reg_1byte(int address, uint32_t value) {
_cs.write(0);
wait_us(10);
_spi.write(address);
_spi.write(value & 0xFF);
wait_us(10);
Pulse_IO_Update();
wait_us(10);
_cs.write(1);
}
Read a 32bit register at the specified address.
uint32_t read_reg_4byte(int address) {
uint32_t value = 0;
_cs.write(0);
wait_us(10);
_spi.write(address | 0x80);
value = _spi.write(0) << 24;
value |= _spi.write(0) << 16;
value |= _spi.write(0) << 8;
value |= _spi.write(0);
wait_us(10);
_cs.write(1);
return value;
}
Read a 24bit register at the specified address.
uint32_t read_reg_3byte(int address) {
uint32_t value = 0;
_cs.write(0);
wait_us(10);
_spi.write(address | 0x80);
value = _spi.write(0) << 16;
value |= _spi.write(0) << 8;
value |= _spi.write(0);
wait_us(10);
_cs.write(1);
return value;
}
Read a 16bit register at the specified address.
uint32_t read_reg_2byte(int address) {
uint32_t value = 0;
_cs.write(0);
wait_us(10);
_spi.write(address | 0x80);
value = _spi.write(0) << 8;
value |= _spi.write(0);
wait_us(10);
_cs.write(1);
return value;
}
Read a 8bit register at the specified address.
uint32_t read_reg_1byte(int address) {
uint32_t value = 0;
_cs.write(0);
wait_us(10);
_spi.write(address | 0x80);
value = _spi.write(0);
wait_us(10);
_cs.write(1);
return value;
}
Write the regsiters
void cfcr1_write(uint32_t reg) {write_reg_4byte(0x00, reg);}
void cfcr2_write(uint32_t reg) {write_reg_3byte(0x01, reg);}
void asf_write(uint32_t reg) {write_reg_2byte(0x02, reg);}
void arr_write(uint32_t reg) {write_reg_1byte(0x03, reg);}
void ftw_write(uint32_t reg) {write_reg_4byte(0x04, reg);}
void pos_write(uint32_t reg) {write_reg_2byte(0x05, reg);}
Read the registers
uint32_t cfcr1_read(void) {return read_reg_4byte(0);}
uint32_t cfcr2_read(void) {return read_reg_3byte(1);}
uint32_t asf_read(void) {return read_reg_2byte(2);}
uint32_t arr_read(void) {return read_reg_1byte(3);}
uint32_t ftw_read(void) {return read_reg_4byte(4);}
uint32_t pos_read(void) {return read_reg_2byte(5);}
reset the AD9951
void reset(void) {
_rst.write(1);
wait(0.01);
_rst.write(0);
}
initialize the AD9951
to use external clock rather than a crystal for the clock
void init (void) {
_rst.write(1);
wait(0.01);
_rst.write(0);
wait_us(10);
cfcr1_write(0x00000202); set SDIO to input only and disable SYNC_CLK
cfcr2_write(0xa6); multiply by 20x, set the VCO_range bit
}
double frequency(double f) {
returns the actual frequency in floating point
uint64_t ftw;
ftw = (int64_t) (f * two_to_32) / ((int64_t) (multiplier * ClockFrequency));
ftw_write((uint32_t) ftw);
ftw = (int64_t) ftw_read();
return (double)((ftw * multiplier * ClockFrequency ) / ((int64_t) two_to_32));
return ftw_read();
}
float amplitude(float amp) {
gives full amplitude with 100.0, zero output for 0.0, returns amplitude
//
uint32_t v;
if (amp >= 100.0) amp = 100.0;
if (amp <= 0.0) amp = 0;
v = (int) ((amp / 100.0) * 16383.0);
asf_write(v);
return (asf_read() * 100.0 / 16383);
}
uint32_t read_register(int i) {
reads and returns the appropriate register
uint32_t v = 99;
switch (i)
{
case 0: v = cfcr1_read();
break;
case 1: v = cfcr2_read();
break;
case 2: v = asf_read();
break;
case 3: v = arr_read();
break;
case 4: v = ftw_read();
break;
case 5: v = pos_read();
break;
}
return v;
}
};
- endif
hello,
I'm a student who wants to work with DDS AD9951 with SPI bus.
here you can find datasheet : http://www.analog.com/static/imported-files/data_sheets/AD9951.pdf
We found where to connect every pins from mbed to DDS ( MBED to DDS :12 to 4 ; 13 to 6 ; 14 to 3 ; GND to RESET )
is that right ?
We want to have a frequency out of 100 Mhz, what kind of word we have to send ?
In the future, we want to sweep from 20MHz to 30 with a step of 10Hz.
Thanks in advance for your help.
RJ