AD9913 Communication Failure

Hi everyone,

My team and I have been working on a little RF-Controller project. The goal of the project is to produce a 3MHz signal , with serial programming, through the AD9913 from adjusting it's frequency tuning word (FTW). However, it doesn't seem like we're able to communicate with the AD9913 at all. Our current configuration contains the Arduino MEGA 2560 as our microcontroller (overkill for a project like this oops) going through a TXB0108 logic level shifter, into the AD9913. I've attached the schematics of our full diagram as well as the diagram from our unit test. When we use a logic analyzer to observe the data going before and after the level shifter, it seemed to match appropriately. However, when we try to measure the output of the AD9913, it only appears to be noise. Our reference clock is connected directly from the Arduino, and our SYNC_CLK produces an 8MHz signal (which is what we set it to). So this indicates, to us, that the chip is getting power. However, when we do a unit test to attempt to turn off the SYNC_CLK, the SYNC_CLK remains on. This suggests to us that we're not able to communicate with the chip for some reason. The possibility of a faulty chip is highly unlikely, as we tested 4 different chips and each one produced the same result. 

One question I had was the following: how important is it to have our reference clock received through our logic level shifter? As of right now, our current configuration has the reference clock ac coupled from the Arduino. Currently we are more suspicious of our hardware setup rather than our software (I attached our code in case anyone wants to review it), but at this point we are out of ideas. Any help would be much appreciated. 

Schematics:

Full Setup: https://gyazo.com/398a9584ea9a5dc2c96ea76d7492d29d

SYNC_CLK Unit Test Setup: https://gyazo.com/ccf1c10d397520c1581ccdf7360e3054

Software:

#include <SPI.h>

//define the pins used on the microcontroller
#define CS_1 53
#define IO_UPDATE_1 22
#define CLOCKOUT 11
#define MASTER_RESET_1 48

//initialize the values for the registers for 3MHz output using 25MHz crystal ref_clk
const uint8_t CRF1_ADDR = 0x00;
volatile uint8_t CRF1_DATA[] = {0x00,0x00,0x00,0x01};
const uint8_t CRF2_ADDR = 0x01;
volatile uint8_t CRF2_DATA[] = {0x14,0x46};
const uint8_t FTW_ADDR = 0x03;
volatile uint8_t FTW_DATA[] = {0x03,0x12,0x6E,0x97};

void setup() {
//configure the pins as INPUT/OUTPUT
pinMode(CS_1, OUTPUT);
pinMode(IO_UPDATE_1, OUTPUT);
pinMode(MASTER_RESET_1, OUTPUT);
pinMode(CLOCKOUT, OUTPUT);

//initialize pin values
digitalWrite(CS_1, HIGH);
digitalWrite(IO_UPDATE_1, LOW);
digitalWrite(MASTER_RESET_1, LOW);

Serial.begin(9600);

SPI.begin();
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

// generate 8MHz reference clock on pin 11
// set up Timer 1
TCCR1A = bit (COM1A0); // toggle OC1A on Compare Match
TCCR1B = bit (WGM12) | bit (CS10); // CTC, no prescaling
// for 8MHz OCR1A = 0, for 4MHz OCR1A = 1, for 2MHz OCR1A = 3
OCR1A = 0; // output every cycle

test1();
}

void test1()
{
int command;
uint8_t CRF1_DATA_TEMP[] = {0x00,0x00,0x00,0x00};
Serial.println("***Test1***");

while(1)
{
Serial.println("Select an option to enable/disable the SYNC_CLK");
Serial.println("1.Enable");
Serial.println("2.Disable");

while(Serial.available() == 0) {}

if(Serial.available() > 0) {
command = Serial.read();

switch (command) {
case '1':
CRF1_DATA_TEMP[1] = 0x00;
write(CRF1_ADDR,CRF1_DATA_TEMP,4);
Serial.println("SYNC_CLK enabled");
break;
case '2':
CRF1_DATA_TEMP[1] = 0x08;
write(CRF1_ADDR,CRF1_DATA_TEMP,4);
Serial.println("SYNC_CLK disabled");
break;
default:
Serial.println("Invalid command");
break;
}
}
Serial.println();
}
}

void reset()
{
digitalWrite(MASTER_RESET_1, HIGH);
delay(100);
digitalWrite(MASTER_RESET_1, LOW);
}

//function to initialize the 9913 registers
void init9913()
{
Serial.println("Init9913()");
write(CRF1_ADDR,CRF1_DATA,4);
Serial.println("CRF1");
write(CRF2_ADDR,CRF2_DATA,2);
Serial.println("CRF2");
write(FTW_ADDR,FTW_DATA,4);
Serial.println("FTW");
}

//function to write data to specific address on the 9913
void write(const uint8_t &address, const uint8_t data[], const int &dataSize)
{
digitalWrite(CS_1, LOW);
SPI.transfer(address);

for(int i = 0; i < dataSize; i++) {
SPI.transfer(data[i]);
}

update();
digitalWrite(CS_1, HIGH);
}

//function to read data stored at specific address on the 9913
void read(const uint8_t &address, const int &dataSize)
{
Serial.print("Reading from: 0x0");
Serial.println(address,16);

digitalWrite(CS_1, LOW);
uint8_t receivedData[dataSize];
uint8_t tempAddr = address;

bitWrite(tempAddr,7,1);
SPI.transfer(tempAddr);

for(int i = 0; i < dataSize; i++) {
receivedData[i] = SPI.transfer(0xFF);
}

Serial.print("Received data: ");

for(int i = 0; i < 2*dataSize; i++) {
Serial.print(receivedData[i],16);
Serial.print(" ");
}

Serial.println();
digitalWrite(CS_1, HIGH);
}

//function to call the IO update feature on the 9913
void update()
{
digitalWrite(IO_UPDATE_1, HIGH);
delay(1);
digitalWrite(IO_UPDATE_1, LOW);
}

void loop() {}



Updated the code It is also important to note that we wish to use a crystal as our reference clock, but since we can't write to the chip, we're using the direct driven approach.
[edited by: DGT at 4:01 AM (GMT -4) on 14 May 2021]
Parents
  • Hello

    I would recommend you to download AD9913 evaluation software and to

    - set it to match your initial condition

    - use the binary viewer to check all registers values

    - double check size of all registers. They are not all at the same size. Any overflow end-up with a crash of the hardware.

    Start with a simple sinus so you can adjust output power to your requirements.

    Be aware that some bits that are set at reset must be programmed again during operations. Using the demo software will help you to figure out exact configuration. Datasheet is not really explicit about it.

    Best Regards

    STH

Reply
  • Hello

    I would recommend you to download AD9913 evaluation software and to

    - set it to match your initial condition

    - use the binary viewer to check all registers values

    - double check size of all registers. They are not all at the same size. Any overflow end-up with a crash of the hardware.

    Start with a simple sinus so you can adjust output power to your requirements.

    Be aware that some bits that are set at reset must be programmed again during operations. Using the demo software will help you to figure out exact configuration. Datasheet is not really explicit about it.

    Best Regards

    STH

Children
No Data