CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Can't initialize AD9852
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Frozen01



Joined: 23 Apr 2009
Posts: 32

View user's profile Send private message

Can't initialize AD9852
PostPosted: Fri May 22, 2009 11:46 am     Reply with quote

Hi All

I am trying to make a DDS frequency generator, but I cannot get the AD9852 to program. I am using a PIC18F45J10. I have it wired as a 3-wire SPI bus.

Looking at the signals on a logic analyzer everything seems correct, but no matter what I do, the AD9852 does not accept commands

Everything is wired correctly, at least I think so.

Does anyone have any experience with the chip??

Thanks

Lou
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 22, 2009 12:34 pm     Reply with quote

If you want help, post a list of the connections (with pin numbers)
between your PIC and the AD5892. Also post any other relevant
connections on the AD5892, such as the S/P SELECT pin (Pin 70).

Also post a short test program that attempts to read and write from
one register in the AD5892, to prove that communications are working.
This program should fit on one screen, if possible. Don't use a lot of
lines initializing PIC peripheral modules that are not relevant to the
problem.

The test program must be short and should compile with no errors if
we paste it into MPLAB (or the CCS IDE). Verify this before posting.
Frozen01



Joined: 23 Apr 2009
Posts: 32

View user's profile Send private message

PostPosted: Sat May 23, 2009 6:37 am     Reply with quote

Ok here are the connections:

DDS_CLK_EN > RB2 > DDS Clock Enable Pin (20 MHZ Oscilator)

Below are Signal Name > PIC PIN > DDS Name and PIN

UD_Clock > RC2 > IO UD Clock Pin 20
SCLK > RC3 > WRB/SCLK Pin 21
SDO > RC4 > A1/SDO Pin 18
SDI > RC5 > A0/SDIO Pin 19
IO_Reset > RD4 > A2/IO Reset Pin 17
DDS_MRESET > RD5 > MASTER RESET 71
DDS_CS > RD6 RDB/CSB' > Pin 22

Simple code

Code:
void ddsInitialize (){
   int temp1, temp2, temp3, temp4;
   printf ("\n\n\rInitializing DDS");
   output_high(DDS_MRESET);            // Set Master Reset HIGH
   delay_us(10);                     // Wait
   output_low(DDS_MRESET);               // Set Master Reset LOW
   delay_us(10);                     // Wait
   output_low(IO_Reset);
   delay_us(10);
   output_high(IO_Reset);
   output_low(DDS_CS);
    spi_write(0x07);                     // Select Control Register
    spi_write(0x10);                     // Control Register Byte 1
   spi_write(0x64);                     // Control Register Byte 2
   spi_write(0x00);                     // Control Register Byte 3
   spi_write(0x21);                     // Control Register Byte 4
   output_high(DDS_CS);
   output_high(DDS_CLK_EN);
   output_low(DDS_CS);
   spi_write(0x87);
      temp1=spi_read();
      temp2=spi_read();
      temp3=spi_read();
      temp4=spi_read();
   output_high(DDS_CS);
      printf("\n\n\r%u\n\r%u\n\n\r%u\n\n\r%u",temp1,temp2,temp3, temp4);
      delay_ms(500);
}


This code should setup the control register to turn off internal updates, and then read the contents of the control register back. After running the code, Pin 20 still has a pulse train coming out of it.

All data pins have 10K pull up resistors. VDD is 3.3 volts. S/P line is pulled down to gnd via a 100K pull down resistor. Clock is a 3.3v cmos. Diff clock pin 64 is pulled to ground via 100k pull down resistor.

CCS version is 4.092

Thanks for your help,

Lou
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat May 23, 2009 7:41 am     Reply with quote

I see two errors at first look:
-IORESET is said to be active high
-SDO is an output at AD9852, thus it has to be connected to PIC SDI and vice versa
Other errors may be present as well.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 23, 2009 11:23 am     Reply with quote

This is not a compilable program. It's just one routine, so we can't see
your #fuses or your #use delay() statement. Also we can't see your
setup_spi() statement, which sets the SPI Mode and clock speed.

In the posted code, in addition to FvM's comments, these lines have
a problem:
Quote:
temp1=spi_read();
temp2=spi_read();
temp3=spi_read();
temp4=spi_read();

The PIC is the SPI master. It must generate the SCLK. To do this,
the spi_read() function must be given a parameter (normally, 0 is used).
Example:
Quote:
temp1=spi_read(0);

Do that for all four lines.
Frozen01



Joined: 23 Apr 2009
Posts: 32

View user's profile Send private message

PostPosted: Sun May 24, 2009 5:15 pm     Reply with quote

Here is my complete code:

Code:
#include "dds1.h"
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

   
void ddsInitialize (){
   int temp1, temp2, temp3, temp4;
   printf ("\n\n\rInitializing DDS");
   output_high(DDS_MRESET);            // Set Master Reset HIGH
   delay_us(10);                     // Wait
   output_low(DDS_MRESET);               // Set Master Reset LOW

   

   delay_us(10);                     // Wait
   output_high(IO_Reset);
   delay_us(10);
   output_low(IO_Reset);
   output_low(DDS_CS);
    spi_write(0x07);                     // Select Control Register
    spi_write(0x10);                     // Control Register Byte 1
   spi_write(0x64);                     // Control Register Byte 2
   spi_write(0x00);                     // Control Register Byte 3
   spi_write(0x21);                     // Control Register Byte 4
   output_high(DDS_CS);
   output_high(DDS_CLK_EN);
   output_low(DDS_CS);
   spi_write(0x87);
      temp1=spi_read(0);
      temp2=spi_read(0);
      temp3=spi_read(0);
      temp4=spi_read(0);
   output_high(DDS_CS);
      printf("\n\n\r%u\n\r%u\n\n\r%u\n\n\r%u",temp1,temp2,temp3, temp4);
      delay_ms(500);
}

void welcomeScreen (){
   output_low (Status_1);
   delay_ms (100);
   output_high (Status_1);
   output_low (Status_2);
   delay_ms (100);
   output_high (Status_2);
   output_low (Status_3);
   delay_ms (100);
   output_high (Status_3);
   output_low (Status_4);
   delay_ms (100);
   output_high (Status_4);
   delay_ms (100);
   printf ("DDS Control Program\r\n\n");
}
void main ()
   {

   delay_ms(2);   
   set_tris_a(0x00);
   set_tris_b(0xC1);
   set_tris_c(0x84);
   set_tris_d(0x00);
   set_tris_e(0x00);   
   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_SS_DISABLED);
   output_high(DDS_CS);
    output_high(IO_Reset);

   delay_us(100);                        // Wait   //set_tris_c(0b10010100);
   welcomeScreen();

      while(1){
      output_low(DDS_CLK_EN);
      delay_ms(500);
      ddsInitialize();
   }   
   printf ("\n\n\rEnter Frequency: ");


dds1.h:

Code:
#include <18F45J10.h>
#device ICD=TRUE
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES EC_IO                    //External clock
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NOPROTECT                //Code not protected from reading
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES PRIMARY                  //Primary clock is system clock when scs=00
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=20000000)
#define Status_1         PIN_A0
#define Status_2            PIN_A1
#define Status_3            PIN_A2
#define Status_4            PIN_A3
#define RS-232_Invalid      PIN_B0
#define PGC               PIN_B6
#define PGD               PIN_B7
#define UD_Clock         PIN_C2
#define RS232_TX         PIN_C6
#define RS232_RX            PIN_C7
#define SK_MOD            PIN_D3
#define IO_Reset            PIN_D4
#define DDS_MRESET         PIN_D5
#define DDS_CS            PIN_D6
#define OSK               PIN_D7
#define DDS_CLK_EN          PIN_B2
#define DDS_SDI            PIN_C5
#define DDS_SDO            PIN_C4
#define DDS_SCK            PIN_C3



#use rs232(baud=9600,parity=N,xmit=RS232_TX,rcv=RS232_RX,bits=8)


I made the changes you suggested and it still does not work. Also the comment about SDO/SDI being wired incorrect, I am using SDO ad my "variable" name, it is wired correctly as I can see the data being written to the pin using a logic analyzer.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 24, 2009 8:42 pm     Reply with quote

Quote:

setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_SS_DISABLED);

The SPI mode is wrong. Look at the timing diagrams on pages 35
and 37 of the AD9852 data sheet.
http://www.analog.com/static/imported-files/data_sheets/AD9852.pdf
It shows the data is sampled on the rising edge of SCLK, and that
SCLK idles at a low level or a high level.
Look at this diagram which shows the timing of the 4 possible SPI modes.
It shows that the AD9852 uses SPI modes 0 or 3:
http://www.totalphase.com/support/kb/10045/#modes

These constants define the SPI modes for the CCS compiler:
Code:

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

Put these lines above main() in your program.

On page 35 of the AD9852 data sheet, it says the maximum SCLK
frequency is 10 MHz. Your PIC oscillator frequency is 20 MHz.
The 18F45J10.h file shows the smallest SCLK divisor is 4. This would
give 20 MHz / 4 = 5 MHz, which is acceptable. However, let's use /16
as a more conservative value. This gives an SCLK of 1.25 MHz.
The SPI_SS_DISABLED constant is only used in SPI slave mode.
Therefore, the setup_spi() statement should be the following:
Code:
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);


Quote:
set_tris_c(0x84);

You're not using fast i/o mode, so there is no need to set the TRIS.
The compiler will do it for you, provided that you use the built-in CCS
functions or the CCS library functions (invoked with #use statements).
Plus, the line above is incorrect. In the 18F45J10, pin C4 is the SDI pin.
This is an input pin. But 0x84 (1000 0100) sets pin C4 as an output.
It's better to let the compiler set the TRIS. It knows which pins should
be inputs and outputs for hardware SPI, and will set them up
automatically when you call the setup_spi() function.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon May 25, 2009 12:48 am     Reply with quote

Quote:
Also the comment about SDO/SDI being wired incorrect, I am using SDO ad my "variable" name, it is wired correctly as I can see the data being written to the pin using a logic analyzer.


Yes, I was refering to your description of the pin wiring and didn't check it.

The problem is most likely in the wrong SPI mode, as PCM programmer mentioned. All Analog chips (or nearly all?) are using SPI mode 0 and 3.
Frozen01



Joined: 23 Apr 2009
Posts: 32

View user's profile Send private message

PostPosted: Tue May 26, 2009 6:53 am     Reply with quote

Thanks for all the input so far.

I made the changes, and it still will not initialize. I cannot program any register at all.

I am wondering if maybe the AD9852 is "cooked"??
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 26, 2009 4:32 pm     Reply with quote

Post a schematic of your circuit, if available. Upload it on to some free
hosting page and post a link to it.

Post your current code. Remove all unnecessary routines. For example,
in your last code, you have the welcomeScreen() routine, which is not
needed. Cut down the code, re-compile it, test it, and post the results.
Also, don't try to program several registers. Just program one register,
and read it back one time (not in a loop). In other words, a minimal
test program.
Frozen01



Joined: 23 Apr 2009
Posts: 32

View user's profile Send private message

PostPosted: Wed May 27, 2009 8:15 am     Reply with quote

Here is the simplified code:

Code:
#include <18F45J10.h>
#device ICD=TRUE
#device adc=8

#FUSES NOWDT, EC_IO, NODEBUG, NOXINST, STVREN
#FUSES NOPROTECT, FCMEN,IESO, PRIMARY

#use delay(clock=20000000)
#define UD_Clock         PIN_C2
#define IO_RESET         PIN_D4
#define DDS_MRESET         PIN_D5
#define DDS_CS            PIN_D6
#define DDS_CLK_EN          PIN_B2
#define DDS_SDI            PIN_C5
#define DDS_SDO            PIN_C4
#define DDS_SCK            PIN_C3

#include <stdio.h>

void main ()
   {
   #define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
   #define SPI_MODE_1  (SPI_L_TO_H)
   #define SPI_MODE_2  (SPI_H_TO_L)
   #define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)
   
   setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_16);
   output_low(DDS_CLK_EN);
   delay_us(10);
   output_high(DDS_MRESET);
   delay_ms(1);
   output_low(DDS_MRESET);
   output_high(IO_RESET);
   delay_us(10);
   output_low(IO_RESET);
   output_low(DDS_CS);
   spi_write(0x07);
   spi_write(0x10);
   spi_write(0x64);
   spi_write(0x01);
   spi_write(0x21);
   output_high(DDS_CS);
   output_high(DDS_CLK_EN);
   delay_us(10);
   output_low(DDS_CS);
   spi_write(0x87);
   spi_read(0);
   spi_read(0);
   spi_read(0);
   spi_read(0);
   output_high(DDS_CS);
   delay_ms(500);
   while(1);
   }


This code should enable the SDO pin so I can run a 3-wire SPI bus.

Schematic is here:
DDS.pdf

Screen Capture of Logic analyzer running above code:
Ttelmah
Guest







PostPosted: Wed May 27, 2009 9:04 am     Reply with quote

Try raising the select line at the start of the code. Remember the lines will be floating when the PIC wakes up, till you send something.

Best Wishes
Frozen01



Joined: 23 Apr 2009
Posts: 32

View user's profile Send private message

PostPosted: Wed May 27, 2009 1:57 pm     Reply with quote

I received this from Analog Devices today. I am going to try this, but I am a bit confused by the HEX data he wants to send. From the data sheet it seems like too many bits...

Quote:
In serial mode, you need to be synchronized to the I/O Update clk.
During the falling edge of the 7th SCLK of any write sequence, the serial interface to the I/O Port Buffer goes into transparent mode to parallel up the serial data inside. If a I/O Update clk occurs during this time, the 8th bit of every byte may or may not be register correctly. It's a race condition, don't let an internal I/O Update occur during the 7th SCLK's falling edge to the 8th SCLK's falling edge. We recommend external I/O Update clk for this reason or else, become synchronous to the internal I/O Update Clk.
External I/O Update clk should help provide the simplest way to become synchronous to the interface.


PROPOSED PROTOCOL:
This protocol will sound simple, but it will deal with the internal I/O Update clk by
avoiding a unknown state. Remember, its running until the end at step 4 below.
1)Power-up and apply the REF CLK, place in serial mode.
2)Send Reset for a high time of at least 10 REF CLK periods.
3)Program the instruction byte to serial address 07 hex.
4)Send the following 24-bits of data. 0000 0000 00 hex
0010 0000 20 hex
0000 0000 00 hex
Wait more than one default period of the internal I/O Update CLK period( REF CLK FREQ / 128).
This will give enough time for an internal I/O Update to occur, placing the device in external I/O Update CLk mode.
5)You can send the remaining 8-bits of the total 32-bits for serial address 07 hex or send a I/O Reset(pin 17).
6) At this point the device is in a known state, external I/O Update clk mode
If you have not gone down this path try it. If you have done all of this let me know.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 27, 2009 3:07 pm     Reply with quote

The control word is 32 bits (4 bytes). He wants you to send the first
3 bytes, do a delay for some time period, and then send the 4th byte.

Look at the MPASM code on this guy's page:
http://www.f6blk.net/main_en.php?page=79
Look at how he handles the IO Update signal. He calls it "IO".
See the INIT_DDS routine and OL52 routines, which pulses the IO line
high at appropriate times.

I would ask Analog Devices tech support for some sample code in C
that shows how to use the serial port. Even if it's pseudo-code, that
would help a lot.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu May 28, 2009 4:33 am     Reply with quote

To mention a more basic possible issue: It can be seen from the block diagram, that processing of the interface data depends on the existence of a valid system clock. Is it present in your circuit?

As another point, the 100k pulldown resistors at S/P_SELECT and DIFF_CLK_ENABLE pins may possibly give undefined input levels.

I don't expect, that the internal update timing issue discussed by Analog is causing the problem. But you can try. You may also want to check, if the chip sends output to SDIO erroneously, by checking the analog signal level at this pin.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group