Ecco il codice completo in un file unico che è possibile provare (anche senza nessun AD9833)
// ******************************************************************************************************************************** //
// ******************* SPI Communication driver for AD9833 DDS with Frame Sync,,, *********************************************** //
// ******************************************************************************************************************************** //
// Last modification: April 2008 //
// Original source: AVRwiz http://greschenz.dyndns.org/?title=AvrWiz //
// Reference 1: http://winavr.scienceprog.com/avr-gcc-tutorial/serial-peripheral-interface-spi-of-avr-microcontrollers.html //
// Reference 2: http://www.mikroe.com/forum/viewtopic.php?t=9976 //
// Modified by: Michael Grant (krazatchu at hotmail dot com) //
// Compiler: GCC / AVR Studio 4 //
// Target device: ATmega8 @ 10 MHz //
// Application: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=62560 //
// ******************************************************************************************************************************** //
#include <avr/io.h>
/*************************************************************************
Function: SPI_init()
Purpose: initialize the SPI bus
**************************************************************************/
void SPI_init (void)
{
DDRB = 0xFF;
PORTB = 0xFF;
DDRB = _BV(PB0) | _BV(PB3) | _BV(PB5); // set SCK,MOSI,PB0 as Fsync
PORTB = _BV(PB5) | _BV(PB0); // SCK and PB0 high
SPCR = _BV(SPE)| _BV(MSTR)| _BV(CPOL); // Enable SPI // Set Master mode // Set clk to inv.
// SPCR |= _BV(SPR0) // Clk speed = fck/4, SPR0,SPR1 = 0,0 // uncomment for fck/16
}
/*************************************************************************
Function: SPI_write16()
Purpose: send a 16bit word to the AD9833
Input: unsigned short data = 16bits
Comment: uses 8bit filter and two consecutive writes while fsync stays low
**************************************************************************/
void SPI_write16 (unsigned short data) // send a 16bit word and use fsync
{
unsigned char MSdata = ((data>>8) & 0x00FF); //filter out MS
unsigned char LSdata = (data & 0x00FF); //filter out LS
PORTB &= ~_BV(PB0); // Fsync Low --> begin frame
SPDR = MSdata; // send First 8 MS of data
// WARNING: BLOCK IN WHILE
while (!(SPSR & (1<<SPIF))); // while busy
SPDR = LSdata; // send Last 8 LS of data
// WARNING: BLOCK IN WHILE
while (!(SPSR & (1<<SPIF))); // while busy
PORTB |= _BV(PB0); // Fsync High --> End of frame
}
/*************************************************************************
Function: Freq_change()
Purpose: change the frequency and select AD9833 onboard register
Input: unsigned short freq_out = frequency, unsigned int select = register 0 or 1
Returns: none
Comment: uses 14 bit filter and adds control words,
**************************************************************************/
void Freq_change ( unsigned long freq_out, unsigned int select ) // take base10 frequency and do frequency hop
{
unsigned short Mclk = 50;
unsigned long freq_reg = freq_out * (268.435456 / Mclk); // make freq register from frequency
unsigned short MS_reg = ((freq_reg >> 14) & 0x3FFF); // filter out MS -- make 2 x 14 bit frequency words
unsigned short LS_reg = (freq_reg & 0x3FFF); // filter out LS -- make 2 x 14 bit frequency words
MS_reg += 0x4000; // add control bits hex = 0x4000
LS_reg += 0x4000; // add control bits hex = 0x4000
if (select == 0 ) { SPI_write16(0x2000);} // prep ad9833 to recieve full 28bit word for freq 0
if (select == 1 ) { SPI_write16(0x2800);} // prep ad9833 to recieve full 28bit word for freq 1
SPI_write16(LS_reg); // send the LS word first, to the ad9833
SPI_write16(MS_reg); // send the MS word last, to the ad9833
}
/*************************************************************************
Function: AD9833_init()
Purpose: Init the AD9833
Input: none
Returns: none
Comment: this function isn't nessecary, can be done manually
**************************************************************************/
void AD9833_init (void)
{
SPI_write16(0x2100); // control word, set output to mid value voltage
SPI_write16(0x7288); // Freq0 registerdata MSB = approx. 29 khz
SPI_write16(0x4017); // Freq0 registerdata LSB = approx. 29 khz
SPI_write16(0xACEA); // Freq1 registerdata MSB = approx. 24 khz
SPI_write16(0x8013); // Freq1 registerdata LSB = approx. 24 khz
SPI_write16(0xC000); // Phase offset of Freq0 = 0
SPI_write16(0xE000); // Phase offset of Freq1 = 0
SPI_write16(0x2000); // control word, set output = sine
}
/*
Arduino code for programming one frequency of the AD9834.
MOSI ==> SDATA
SCK ==> SCLK
PB0 ==> FSYN
*/
void setup()
{
Serial.begin(115200);
SPI_init();
AD9833_init();
}
unsigned long i = 100;
void loop()
{
// After 1100 cycle freeze in Freq_change, problem is in SPI_write16
Freq_change(i, 0);
Serial.println(i);
i+=1;
}