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

2MHz sine waveform using AD9833 and PIC18F4580
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
syamin0712



Joined: 23 Aug 2015
Posts: 14

View user's profile Send private message

2MHz sine waveform using AD9833 and PIC18F4580
PostPosted: Sun Aug 23, 2015 9:00 pm     Reply with quote

Hi everyone,
I need some help for those who have experience in generating sine waveforms using AD9833 and PIC18F4580.

This is my first experience using SPI to code the sine waveform from PIC18F4580 as a master and AD9833 as the slave.

I set the pin between PIC18F4580 and AD9833 as follows:

RC4/SDI/SDA ---- SDATA
RC3/SCK/SCL ---- SCLK
RA5/SS ---- FSYNC

To generate the 2MHz: By using the formula in AD9833 data sheet page 15, while assuming MCLK is 40MHz. I have set the FREQ register to 13421773 decimal number (110011001100110011001101) in binary.

Could anybody check what is wrong with my code:
Code:

#device PIC18F4580
//configure a 10MHz crystal to operate at 40MHz, // System setting - Use 10MHz XTAL with PLL. New Freq: 10MHz x 4 = 40Mhz.
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG
#define OSC_PLL_ON
#use delay(clock=10000000)
#use spi(DO= PIN_C4 , CLK = PIN_C3, ENABLE = PIN_A5, BITS = 16, MASTER, ENABLE_ACTIVE = 0, MSB_FIRST, IDLE = 1)

//DO=SDATA/SDA pin,
//CLK=SCLK/SCK pin,
//ENABLE=FSYNC/SS pin,
//BITS=16 is max num of bit in one transfer is 16,
//MASTER=PIC is master and AD9833 is slave,
//ENABLE_ACTIVE = 0 is FSYNC pin is active low,
//MSB_FIRST is accept MSB of each transfer first
//IDLE=1 is FSYNC always high when not in use


void main()
{

   while(1)
   {
      // activate control register; both LSB & MSB FREQ write consequtively; enable reset; enable sinewaveform signal
     spi_xfer(0b0010000100000000);
   
     //on FREQ0 for generate 2MHz if using MCLK=40MHz ; 13421773 in decimal
     spi_xfer(0b100110011001101); 
     spi_xfer(0b0100001100110011);
     
     //on PHASE0 with zero phase shift
     spi_xfer(0b1100000000000000); 
     
     //activate control register; both LSB & MSB FREQ write ; disable reset; enable sinewaveform signal
     spi_xfer(0b0010000000000000);
   }

}

When I compile these two errors appear:
The function of #use spi shown an error
"USE parameter value is out of range. Not a number. PIN_C4"
and at void main() it shown "I/O error 131".

What is meant by that statement?
Ttelmah



Joined: 11 Mar 2010
Posts: 19510

View user's profile Send private message

PostPosted: Mon Aug 24, 2015 1:10 am     Reply with quote

if using the PLL, the _clock_ in the clock statement, must be set to the actual speed the chip is running. Otherwise all chip timings will be wrong. However I see no sign that you are using the PLL. You need the H4 fuse, instead of the HS fuse to select this.

The hardware SPI, requires all 3 pins are used. You can disable or not use the receive part after setting it up, but set it up with:
Code:

//There is a major problem here. You are defining the chip, but not including
//it's definitions:...
#include <18F4580.h> //This both defines the chip, and includes everything.
//configure a 10MHz crystal to operate at 40MHz, // System setting - Use 10MHz XTAL with PLL. New Freq: 10MHz x 4 = 40Mhz.
#fuses H4,NOWDT,NOPROTECT,NOLVP,NODEBUG

#use delay(clock=40000000)
#use spi(SPI1, MODE=3, ENABLE=PIN_A5, STREAM=AD9833)

The enable pin is specified to default to active low. MSB_FIRST is standard for SPI.
Look at the syntax to include the chip and define it...

Then your transfers must say what size you want to send. The figure given in the #use SPI, is the _maximum_ that can be transferred in a single transaction - defaults to 32bits, so you never need to change this normally.

Code:

#define RESET 0x0100
#define WRITE_FREQ0 0x2000
#define RUN 0
#define PHASE0_ZERO 0xC000
#define spi_14(x) spi_xfer(AD9833,(x & 0x3FFF) | 0x4000,16)

void write_val_freq0(int32 divisor)
{
   //Do the maths to send 28bits to freg - more reliable than DIY
   spi_14(divisor); //send 14 LSb's
   spi_14((divisor>>14)); //then the next 14 bits
}

void main()
{
   setup_adc_ports(NO_ANALOGS); //A5 is an analog pin - make sure this
   //is setup to digital.
   while(1)
   {
     // activate control register; both LSB & MSB FREQ write consecutively
     // enable reset
     spi_xfer(AD9833, RESET | WRITE_FREQ0, 16);
   
     //on FREQ0 for generate 2MHz if using MCLK=40MHz
     //13421773 in decimal
     write_val_freq0(13421773); //setup FREQ0
         
     //on PHASE0 with zero phase shift
     spi_xfer(AD9833, PHASE0_ZERO, 16);
     
     //activate control register
     //disable reset; enable sinewaveform signal
     spi_xfer(AD9833, RUN, 16);

     //generally you don't want to keep sending data to chips 'non stop'...
     //with your existing code, only a few uSec after getting here, the chip
     //would be programmed back to RESET, so the waveform would stop
     //since the waveform doesn't start till 8 clocks after the RESET
     //goes off, there would be almost nothing on the output.....
     delay_ms(1000); //output the waveform for a second
   }
}


Hopefully you see something....
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Aug 24, 2015 3:12 am     Reply with quote

MCLK max is 25MHz (i.e. min period 40ns), so running at 40MHz is out. Getting 2MHz sine from 25MHz is not going to be great, and wouldn't be possible at 50% duty cycle even with a square wave.

Personally I wouldn't bother with all the complexity of trying to transfer wide words to the AD9833. I'd just use the hardware SPI and send sufficient bytes to do the job, and handle CE/FSYNC myself rather than asking the compiler code to do it ot for me. That way I could make sure I got what I wanted. I certainly would not represent the data/numbers to be sent in binary format: 0b011100010010! There's far too much that can go wrong, and it would do my head in.
Ttelmah



Joined: 11 Mar 2010
Posts: 19510

View user's profile Send private message

PostPosted: Mon Aug 24, 2015 5:37 am     Reply with quote

He doesn't say where he is getting 40MHz from. May be that he is thinking the PIC clock is the same as that for the AD.
Obviously the PIC can merrily run at 40MHz, while the synthesiser needs it's own crystal/clock. You could program the PIC PWM to give a 10MHz output, and use this to feed the clock.

Going DIY on the enable, is really a bit unnecessary. Given that #use spi supports long transfers and will nicely handle waiting till the byte/word has sent before releasing the enable, and this has been working now for many dozens of compiler releases. In the 'old days' with setup_spi, this was needed, but now it is perfectly acceptable to use the compiler functions.

Agree wholeheartedly about the binary values. Too easy to just get one digit in the wrong place. Waste hours looking for a fault that isn't there...
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Aug 24, 2015 10:58 am     Reply with quote

it is also not too hard to make the following operate with a single
AD9833 either.

http://www.ccsinfo.com/forum/viewtopic.php?t=53564&highlight=ad9833
syamin0712



Joined: 23 Aug 2015
Posts: 14

View user's profile Send private message

PostPosted: Mon Aug 24, 2015 1:06 pm     Reply with quote

Hi all,
Actually i don't know what is the correct way of setup HSPLL in ccs...im just try and error. TQ Ttelmah...i'll try to edit my code.

Yup,actually at first i think the ad9833 clock is same as the pic clock.
But, I'm wrong. The setting of HSPLL of pic clock will not effect the clock of ad9833.

So, i think to make it safe, is it possible if i gonna use the same value of xtal for pic and ad9833? I mean I'm use 20MHz xtal for operate the pic and connected the same xtal to the MCLK pin at ad9833 as the clock for ad9833?
is it possible?

Also, as I said before this is my first time to write a code using spi mode. Thus, i referred this link as my reference.
http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Aug 24, 2015 1:34 pm     Reply with quote

Quote:
use the same value of xtal for pic and ad9833?


I have shared the PIC crystal oscillator drive side with up to 3 AD9833's
and it can work very well
BUT :
I buffered it with a 74HC04 inverter to avoid any possible instability for the PIC source.
AND
never used greater than an 8.38mhz crystal


i use multiple "common clocked" AD9833 's as a building block in a
multi-detector synchronous demodulator , with great joy.

i'd bet i could get away with driving a single 9833 @ 20Mhz w/o the buffering BUT would keep that clock drive line VERY SHORT !!!

FYI: an 8.388608 mhz crystal is especially wonderful for the Ad9833 and when used with the PIC HSPLL -you still see it at the XO-out but your internal Fosc becomes 33.5 mhz . nothing to sneeze at speed wise .
syamin0712



Joined: 23 Aug 2015
Posts: 14

View user's profile Send private message

PostPosted: Mon Aug 24, 2015 10:43 pm     Reply with quote

Hi all,

I think i have made a wrong selection the pin between AD9833 and PIC18F4580. After I referred the microchip forum, the correct selection is as follow:

AD9833 PIC18F4580

FSYNC RE2/CS/AN7
SDATA RC5/SDO
SCLK RC3/SCL/SCL

This is the link of the forum:
http://www.microchip.com/forums/m406866.aspx

Also, I just use oscillator 20MHz for PIC with HS and connect the pin OSC/RA6 from PIC to the MCLK of AD9833. So that, the MCLK is also 20MHz.

For desired frequency of 2MHz; with 20MHz MCLK I got the value of frequency register is 26843546 in decimal.

Then, I edit the programming from Ttelmah.
Code:

#include <18F4580.h> //This both defines the chip, and includes everything.
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG

#use delay(clock=20000000)
#use spi(SPI1, MODE=3, ENABLE=PIN_E2, STREAM=AD9833)

#define RESET 0x0100  //initialize reset bit D8=1
#define WRITE_FREQ0 0x2000 //initialize LSB & MSB write consecutively, D13=1
#define RUN 0          //intialize give output after reset off
#define PHASE0_ZERO 0xC000  //initalize PHASE0 use
#define spi_14(x) spi_xfer(AD9833,(x & 0x3FFF) | 0x4000,16)
//0x4000 is the register for FREQ0

void write_val_freq0(int32 divisor)
{
   //Do the maths to send 28bits to freg - more reliable than DIY
   spi_14(divisor); //send 14 LSb's
   spi_14((divisor>>14)); //then the next 14 bits
}

void main()
{
   setup_adc_ports(NO_ANALOGS); //E2 is an analog pin - make sure this
   //is setup to digital.
   while(TRUE)
   {
     // activate control register; both LSB & MSB FREQ write consecutively
     // enable reset
     spi_xfer(AD9833, RESET | WRITE_FREQ0, 16);
   
     //on FREQ0 for generate 2MHz if using MCLK=20MHz same as PIC clock
     //26843546 in decimal
     write_val_freq0(26843546); //setup FREQ0
         
     //on PHASE0 with zero phase shift
     spi_xfer(AD9833, PHASE0_ZERO, 16);
     
     //activate control register
     //disable reset; enable sinewaveform signal
     spi_xfer(AD9833, RUN, 16);

     //generally you don't want to keep sending data to chips 'non stop'...
     //with your existing code, only a few uSec after getting here, the chip
     //would be programmed back to RESET, so the waveform would stop
     //since the waveform doesn't start till 8 clocks after the RESET
     //goes off, there would be almost nothing on the output.....
     delay_ms(1000); //output the waveform for a second
   }
}


No error shown but when I pin the SCLK at AD9833 it showed a pulse same as for SDATA. But, the Vout pin i think it showed just a noise because the reading is too small and even the frequency is not 2MHz.
I attached the figure for further reference.

Could anybody help me.
http://obrazki.elektroda.pl/2945806400_1440477712.png
http://obrazki.elektroda.pl/3301420700_1440477713.png
http://obrazki.elektroda.pl/8147298300_1440477713.png
http://obrazki.elektroda.pl/3497403900_1440477713.png
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 24, 2015 11:29 pm     Reply with quote

The SPI mode is wrong:
Quote:
#use spi(SPI1, MODE=3, ENABLE=PIN_E2, STREAM=AD9833)

The AD9833 data sheet (pg. 20) says the SPI mode parameters are:
Quote:
• SCK idles high between write operations (CPOL = 0)
• Data is valid on the SCK falling edge (CPHA = 1)

This is SPI mode 1. See the following diagram:
http://www.totalphase.com/support/articles/200349236-SPI-Background#modes
Also, Figure 4 in the data sheet shows the same thing. SCLK idles low
and samples on the falling edge. That's mode 1. Change the #use spi()
statement to MODE=1.
Ttelmah



Joined: 11 Mar 2010
Posts: 19510

View user's profile Send private message

PostPosted: Tue Aug 25, 2015 12:46 am     Reply with quote

Apologies. I did a Google search for AD9833 SPI mode number, and accepted what somebody had posted. Didn't check.... Embarassed
syamin0712



Joined: 23 Aug 2015
Posts: 14

View user's profile Send private message

PostPosted: Tue Aug 25, 2015 1:03 am     Reply with quote

I have changed into mode 1 but what i got was still not a desired sinewaveform even the shape changes.

http://obrazki.elektroda.pl/1147179900_1440485444.png

Is there any coding that I have to do or missed?

or it is actually MODE 2?
coz when i changed into MODE 2 the frequency is look like 2 MHz but content of ripple and the Vp-p is still less than 1Vp-p.

http://obrazki.elektroda.pl/5027052000_1440486146.png

Besides, what is actually the desired voltage amplitude peak-peak that I should have?it should be 5 Vp-p i'm right? coz the max output from pic is 5Vp-p
syamin0712



Joined: 23 Aug 2015
Posts: 14

View user's profile Send private message

PostPosted: Tue Aug 25, 2015 1:52 am     Reply with quote

I think the peak to peak amplitude will depends on the frequency that we want. I have referred the data sheet page 18,Figure 26. The formula of DAC OUTPUT I think will give the final amplitude of Vout.

Also, I found one blog that said the
Quote:
the output was just around 250mV peak-to-peak.


http://www.electronics-lab.com/tag/ad9833/

So, i think it will not appear 5Vp-p from AD9833 and need to use the amplifier circuit to get the desired Vp-p.

I am right?
syamin0712



Joined: 23 Aug 2015
Posts: 14

View user's profile Send private message

PostPosted: Tue Aug 25, 2015 4:03 am     Reply with quote

Quote:
or it is actually MODE 2?
coz when i changed into MODE 2 the frequency is look like 2 MHz but content of ripple and the Vp-p is still less than 1Vp-p.

http://obrazki.elektroda.pl/5027052000_1440486146.png


And when I make it bigger..its look like the signal is built from the digital point.
http://obrazki.elektroda.pl/7927611700_1440496782.png

Is there any approach that I can make it as a smooth sine wave?using coding?

the configuration hardware circuit for AD9833 I took from this link as I attached the link.
http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833
Ttelmah



Joined: 11 Mar 2010
Posts: 19510

View user's profile Send private message

PostPosted: Tue Aug 25, 2015 4:17 am     Reply with quote

Your amplifier seems to be showing very significant overshoot, that is making it worse....

Look at reducing the high frequency gain of the amplifier. At the moment it is behaving like an audio amplifier that has the treble turned right up....

Also have you checked your scope probe compensation recently?.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Aug 25, 2015 11:12 am     Reply with quote

item one:

your approximate RMS value is the 200 mv i expect from the part or close enough BUT if you copied this design then a KEY component is MISSING!!!!

connect the OUTPUT pin to ground via a 220 ohm resistor and check your waveform again.

NOTE: i always use this part terminated into 220 ohms and FED forward to the ultimate load - by a well designed PI section 3 element L-C low pass filter too.

for certain of my applications a -60db 3rd harmonic is excessive - but thats just the nature of the part @ 10 it res
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