Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Interfacing AD9850 DDS module to PIC18F4520 using C18 compiler

Status
Not open for further replies.

ahsoopk

Member level 5
Joined
Mar 12, 2010
Messages
81
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
2,103
Hi all,

Thanks for taking time to look at my post. I am trying to control AD9850 DDS module using pic18f4520 using C18 and MPLAB.

AD9850 takes in 40bit long serial tuning word and formula to calculate the word is as follows

phase_delta= (Foutx2^32)/Clock_in

I am using 125MHz clock to generate 30MHz Fout. I am initializing the phase_delta, Fout and Clock_in as Floating point varaibles, and watching the variable in MPLAB's watch window. But I get some garbage values, not sure what are those.

Secondly even I consider that garbage value as my result I want to send it bit by bit to the AD9850 chip, so I want to perform bitwise AND operation between phase_delta value and predefined 32bit long mask and keep LEFT SHIFTING the mask to generate bit by bit data. Compiler doesn't let me do that either as it says Integer operands required for bitwise AND.

I am really stuck I am new to microcontroller/C business and would really appreciate if someone can help. If someone has done this themselves before than can they please take me through step by step if possible, otherwise hints and suggestions will be much appreciated.

Regards,
 

You should be able to send the data using the SPI module of the PIC. It would make communication much easier. As far as the garbage data, I would recommend calculating what the data should be and hard coding it to the SPI code to debug the communication first. Then once you know you can correctly send data to the DDS, then you can work on the calculations to get the correct frequency.
 

hello,

I just finish to build my GenBF with a DDS AD9850
have a look on my source ( C18), even written for a 18F46k22, it could help you...
**broken link removed**
 
Hi spudboy488

I thought about this but then I thought rather than learning SPI standard and getting stuck in something that i have never done before, why shouldn't I start with slightly easy/basic and use register pins.. that way I shall understanding the clocking of data as well. since I am new to micro-controller stuff I want to learn the basic of clocking data etc..
 

I don't understand your approach,
because in my example , i don't use SPI hardware, but i build a like SPI in software.
So use of register and shift data..

if you want to work deeper with register, you have to work in ASM .not in C langage

- - - Updated - - -

I don't understand your approach,
because in my example , i don't use SPI hardware, but i build a like SPI in software.
So use of register and shift data..

if you want to work deeper with register, you have to work in ASM .not in C langage
 

I don't understand your approach,
because in my example , i don't use SPI hardware, but i build a like SPI in software.
So use of register and shift data..

if you want to work deeper with register, you have to work in ASM .not in C language

Sorry Paulfjujo for the confusion this reply was for someone else not for you...
I went through you project and picked up bits and pieces as I am not a programmer and have near to none experience in programming.. Is it possible to have the same code with english comments, it seems like you have done a very good job and comments define a lot, its a shame I can't understand that language..

I would really appreciate if you could provide this code with english comments...
 

I don't understand your approach,
because in my example , i don't use SPI hardware, but i build a like SPI in software.
So use of register and shift data..

if you want to work deeper with register, you have to work in ASM .not in C language

Sorry Paulfjujo for the confusion this reply was for someone else not for you...
I went through you project and picked up bits and pieces as I am not a programmer and have near to none experience in programming.. Is it possible to have the same code with english comments, it seems like you have done a very good job and comments define a lot, its a shame I can't understand that language..

I would really appreciate if you could provide this code with english comments...


Hi,

I have put some code together after looking at Paulfjujo's code. But still no luck DDS doesn't work I am getting some random frequency in Hz when I am trying to generate 4MHz.

I have connected both GND pins to DC supply GND and both Vcc pins to +5V rest you can see in code... please help its driving me crazzzzzzzy.
I am using external 4MHz oscillator for PIC18F4520.

#include <p18f4520.h>
#include <delays.h>
#include <math.h>


#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config OSC=HS

#define SDATA LATBbits.LATB5 // Serial data line
#define W_CLCK LATBbits.LATB6 // Clock line to clock in data
#define FQ_UD LATBbits.LATB7 // Frequency up date line
#define AD9850_CONTROL_WORD 0x00 // 8 Byte zeros
#define AD9850_FREQUENCY 4000000 // 4MHz
#define AD9850_FREQUENCY_FACTOR 34.35973837 // 2^32 divided by 125MHz
#define Byte unsigned char // Define CHAR as Byte data type


/*----------------------------------------------------------------------------------------
This structure's variable will be defined in UNION to access 32bit data in chunks of 8bits
-----------------------------------------------------------------------------------------*/
struct DataBytes
{
near Byte Byte0;
near Byte Byte1;
near Byte Byte2;
near Byte Byte3;
};


/*---------------------------------------------------------------------------------------
Since UNION's all variables point to the same storage location we define one variable
to get the 32bit data so it is defined as LONG data type, and to put it out as 8bit word
we define DATABYTE STRUCTURE's variable and access each element at a time to access 8bits
at one time.
------------------------------------------------------------------------------------------*/
union //ByteLevelAccess
{
near unsigned long TuningWord;
near struct DataBytes DDS;
}AD9850_Serial_Data;


/*---------------------------------------
Prototype declerations of the functions
----------------------------------------*/

void Init_AD9850(void);
void SendSerialDataByteToAD9850(unsigned char Data);
void AD9850_Charge_Freq(float Freq);


/*--------------------------------------------------------------------------------------------
MAIN FUCNTION
---------------------------------------------------------------------------------------------*/

void main()
{
ADCON1 = 0x0F; // All pins are now digital I/O
TRISB = 0; // make all pin output
Init_AD9850();
AD9850_Charge_Freq(AD9850_FREQUENCY);

return;
}





/*-------------------------------------------------------------------------------------------
FUCNTION TO INITIALIZE THE AD9850 FOR SERIAL DATA INPUT
--------------------------------------------------------------------------------------------*/


void Init_AD9850(void)
{
Byte counter;

//initialize CLOCK,FRQ_UPDATE and SERIAL DATA lines with zero
//------------------------------------------------------------

SDATA=0;
W_CLCK=0;
FQ_UD=0;

//------------------------------------------------------------

//Reset address pointer to W0 (first word) in AD9850
//--------------------------------------------------

FQ_UD=1;
Delay10TCY();
FQ_UD=0;
Delay10TCY();

//---------------------------------------------------

/*Initialize AD9850 for serial data input by setting W32=0, W33=0 and W34=0
by using following sequence
W_CLCK = 1
W_CLCK = 0
FQ_UD = 1
FQ_UD 0
Write W32=0, W33=0 and W34=0 sequencially and respectively to AD9850 chip
FQ_UD = 1 to reset the control word pointer to W0
FQ_UD = 0
--------------------------------------------------------------------------*/

W_CLCK = 1;
Delay10TCY();
W_CLCK = 0;
Delay10TCY();


FQ_UD = 1;
Delay10TCY();
FQ_UD = 0;
Delay10TCY();

counter=0;

// Following loop sends zero three times to AD9850 as W32=0,W33=0 & W34=0

do
{
SDATA = 0;
W_CLCK = 1;
Delay10TCY();
W_CLCK = 0;
Delay10TCY();

counter++;
}while (counter<3);

Delay10TCY(); //for settling of all the signals

//----------------------------------------------------------------------------

//Reset the control word pointer to W0 in AD9850
//-----------------------------------------------

FQ_UD = 1;
Delay10TCY();
FQ_UD = 0;
Delay10TCY(); // for settling of all the signals

}

/*--------------------------------------------------------------------------------------------
AD9850_Charge_Freq FUNCTION DEFINATION
---------------------------------------------------------------------------------------------*/

void AD9850_Charge_Freq(float Freq)
{
AD9850_Serial_Data.TuningWord = (long) (Freq * AD9850_FREQUENCY_FACTOR);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. Byte0);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. Byte1);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. Byte2);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. Byte3);
SendSerialDataByteToAD9850(AD9850_CONTROL_WORD);

Delay10TCY();

FQ_UD = 1; Delay10TCY(); // TO UPDATE THE FREQUENCY AFTER 18 CLOCK CYCLES
FQ_UD = 0; Delay10TCY();

FQ_UD = 1; Delay10TCY(); // TO RESET THE CONTROL WORD POINTER TO W0
FQ_UD = 0; Delay10TCY();
}


/*--------------------------------------------------------------------------------------------
SendSerialDataByteToAD9850 FUNCTION DEFINATION
---------------------------------------------------------------------------------------------*/

void SendSerialDataByteToAD9850(unsigned char Data)
{
Byte counter = 0;

do
{
SDATA = 0;
if(Data&1) SDATA=1; // Check LSB bit
Data = Data>>1; // RIGHT SHIFT THE DATA BY ONE BIT
Delay10TCY();
W_CLCK = 1; // CLOCK IN THE DATA BIT
Delay10TCY();
W_CLCK = 0;

counter++;
}while(counter<8);

}
 

hello,

I am using external 4MHz oscillator
is it a Quartz or External oscillator ?

About AD9850 Device hardware:
Did you connect D0 to Gnd , D1 & D2 to +VCC
to force AD9835 in serial mode ?
And force Reset pin to Gnd !

Don't use a constant for control word.
Be sure to init control word to Zero.


Code:
unsigned char AD9850_CONTROL_WORD;

void main()
{
ADCON1 = 0x0F; // All pins are now digital I/O
TRISB = 0;	// make all pin output
[B]AD9850_CONTROL_WORD=0;[/B]
Init_AD9850();
AD9850_Charge_Freq(AD9850_FREQUENCY);
[B]while(1);[/B]
}
 

"is it a Quartz or External oscillator ?"

It is a 4MHz Quartz crystal. Am I specifying it right or is it wrong? I would really appreciate if you could elaborate the use of
#pragma config OSC=?...

- - - Updated - - -

hello,


is it a Quartz or External oscillator ?

About AD9850 Device hardware:
Did you connect D0 to Gnd , D1 & D2 to +VCC
to force AD9835 in serial mode ?
And force Reset pin to Gnd !

Don't use a constant for control word.
Be sure to init control word to Zero.


Code:
unsigned char AD9850_CONTROL_WORD;

void main()
{
ADCON1 = 0x0F; // All pins are now digital I/O
TRISB = 0;	// make all pin output
[B]AD9850_CONTROL_WORD=0;[/B]
Init_AD9850();
AD9850_Charge_Freq(AD9850_FREQUENCY);
[B]while(1);[/B]
}


I forgot to ask why are you using while(1); at the end of main() function.. please forgive me for asking basic questions but I am at very early stage of learning C.

regards,

- - - Updated - - -

I spent nearly 5 hours today to get it working but nothing is happening. I have connected everything according to your schematic and made changes in the code as you suggested but nothing is happening.

I have connected the GND pins to the pcb GND plane, +5V to Vcc and -5V of power supply to the GND plane of the PCB.

if i replace while(1) from main with return; statement I get some jumping garbage frequencies but otherwise nothing happens. I can see on oscilloscope DATA,CLCK and FUD signal at the start up of pic controller but then all pins go to zero state.

One thing that I have noticed from DATASHEET that D0 and D1 are connected to Vcc and D2 is connected to GND for serial comms. Please check and confirm who is correct you or the DATASHEET.

I would really appreciate you help on this....

Regards,
 

hello,

One thing that I have noticed from DATASHEET that D0 and D1 are connected to Vcc and D2 is connected to GND for serial comms. Please check and confirm who is correct…

Not correct , you can see the schematic and photo of wiring on
my web page.
remark : i am not using AD9850 directly,but a breakboard
with an AD9850.
I suppose the correspondance D0..D7 of breakboard is the same as
D0..D7 of AD9850 !
Another people build successfully this application
with AD9850..the main difference is using a Pic18F46k22 and fclock 40Mhz
but i think no problemo with your pic ..
if hardware init is ok,because use only one port B and timming is not
critical.
 

hello,



Not correct , you can see the schematic and photo of wiring on
my web page.
remark : i am not using AD9850 directly,but a breakboard
with an AD9850.
I suppose the correspondance D0..D7 of breakboard is the same as
D0..D7 of AD9850 !
Another people build successfully this application
with AD9850..the main difference is using a Pic18F46k22 and fclock 40Mhz
but i think no problemo with your pic ..
if hardware init is ok,because use only one port B and timming is not
critical.


Hi

After another 3 nights of work and stressful work, still at the same point where I started... Its not working no matter what ever I do. I have tried with increased delay with less delay, nothings gives a different output. tried with different daughter boards thinking that device might have died during experiments but nothing helped.

I have changed code for easy reading and posting here again and will really appreciate if you could tell me anything that I am doing wrong.

I am using external 4MHz XTAL and PIC18F4520

#include <p18f4520.h>
#include <delays.h>
#include <math.h>


#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config OSC=XT

#define RESET_AD9850 LATBbits.LATB4 // Reset line
#define SDATA LATBbits.LATB5 // Serial data line
#define W_CLCK LATBbits.LATB6 // Clock line to clock in data
#define FQ_UD LATBbits.LATB7 // Frequency up date line
//#define AD9850_CONTROL_WORD 0x00 // 8 Byte zeros
#define AD9850_FREQUENCY 4000000 // 4MHz
#define AD9850_FREQUENCY_FACTOR 34.35973837 // 2^32 divided by 125MHz
#define Byte unsigned char // Define CHAR as Byte data type


/*----------------------------------------------------------------------------------------
This structure's variable will be defined in UNION to access 32bit data in chunks of 8bits
-----------------------------------------------------------------------------------------*/
struct DataBytes
{
near Byte Byte0;
near Byte Byte1;
near Byte Byte2;
near Byte Byte3;
};


/*---------------------------------------------------------------------------------------
Since UNION's all variables point to the same storage location we define one variable
to get the 32bit data so it is defined as LONG data type, and to put it out as 8bit word
we define DATABYTE STRUCTURE's variable and access each element at a time to access 8bits
at one time.
------------------------------------------------------------------------------------------*/
union //ByteLevelAccess
{
near unsigned long TuningWord;
near struct DataBytes DDS;
}AD9850_Serial_Data;

/*------------------------------------------------------------------------------------------
CONTROL BYTE FOR AD9850
-------------------------------------------------------------------------------------------*/

unsigned char AD9850_CONTROL_WORD;

/*---------------------------------------
Prototype declerations of the functions
----------------------------------------*/

void Init_AD9850(void);
void SendSerialDataByteToAD9850(unsigned char Data);
void AD9850_Charge_Freq(float Freq);
void AD9850_DATA_IN_CLOCK(void);
void AD9850_RESET(void);
void FRQ_UD_AD9850(void);


/*--------------------------------------------------------------------------------------------
MAIN FUCNTION
---------------------------------------------------------------------------------------------*/

void main()
{
ADCON1 = 0x0F; // All pins are now digital I/O
TRISB = 0; // make all pin output
PORTB=0;
AD9850_CONTROL_WORD = 0; //initialize control word
Init_AD9850();
Delay10TCY();
AD9850_Charge_Freq(AD9850_FREQUENCY);

// return;
while(1);
}





/*-------------------------------------------------------------------------------------------
FUCNTION TO INITIALIZE THE AD9850 FOR SERIAL DATA INPUT
--------------------------------------------------------------------------------------------*/


void Init_AD9850(void)
{
Byte counter;

//initialize CLOCK,FRQ_UPDATE and SERIAL DATA lines with zero
//------------------------------------------------------------

//SDATA=0;
//W_CLCK=0;
//FQ_UD=0;

//------------------------------------------------------------

//Reset address pointer to W0 (first word) in AD9850
//--------------------------------------------------

AD9850_RESET();

//---------------------------------------------------

/*Initialize AD9850 for serial data input by setting W32=0, W33=0 and W34=0
by using following sequence
W_CLCK = 1
W_CLCK = 0
FQ_UD = 1
FQ_UD 0
Write W32=0, W33=0 and W34=0 sequencially and respectively to AD9850 chip
FQ_UD = 1 to reset the control word pointer to W0
FQ_UD = 0
--------------------------------------------------------------------------*/

AD9850_DATA_IN_CLOCK();

FRQ_UD_AD9850();

counter=0;

// Following loop sends zero three times to AD9850 as W32=0,W33=0 & W34=0

do
{
SDATA = 0;
AD9850_DATA_IN_CLOCK();
counter++;
}while (counter<3);

//Delay10TCY();//Delay10TCY();Delay10TCY(); //for settling of all the signals

//----------------------------------------------------------------------------

//Reset the control word pointer to W0 in AD9850
//-----------------------------------------------

FRQ_UD_AD9850();

}

/*--------------------------------------------------------------------------------------------
AD9850_Charge_Freq FUNCTION DEFINATION
---------------------------------------------------------------------------------------------*/

void AD9850_Charge_Freq(float Freq)
{
AD9850_Serial_Data.TuningWord = (long) (Freq * AD9850_FREQUENCY_FACTOR);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS.Byte0);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS.Byte1);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS.Byte2);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS.Byte3);
SendSerialDataByteToAD9850(AD9850_CONTROL_WORD);

Delay10TCY();
Delay10TCY();
Delay10TCY();

FRQ_UD_AD9850();

FRQ_UD_AD9850();
}


/*--------------------------------------------------------------------------------------------
SendSerialDataByteToAD9850 FUNCTION DEFINATION
---------------------------------------------------------------------------------------------*/

void SendSerialDataByteToAD9850(unsigned char Data)
{
Byte counter = 0;

do
{
SDATA = 0;

if(Data&1) SDATA=1; // Check LSB bit

Data = Data>>1; // RIGHT SHIFT THE DATA BY ONE BIT

AD9850_DATA_IN_CLOCK();

counter++;
}while(counter<8);

}

/*--------------------------------------------------------------------------------------------
AD9850_DATA_IN_CLOCK FUNCTION DEFINATION
---------------------------------------------------------------------------------------------*/

void AD9850_DATA_IN_CLOCK()
{


W_CLCK = 1;
Delay10TCY();
Delay10TCY();
W_CLCK = 0;
Delay10TCY();
Delay10TCY();
Delay10TCY();
Delay10TCY();


}


/*--------------------------------------------------------------------------------------------
RESET_AD9850 FUNCTION DEFINATION
---------------------------------------------------------------------------------------------*/

void AD9850_RESET()
{

RESET_AD9850=1;
Delay10TCY();
RESET_AD9850=0;
Delay10TCY();
Delay10TCY();
Delay10TCY();
Delay10TCY();
Delay10TCY();
Delay10TCY();

}

/*--------------------------------------------------------------------------------------------
FRQ_UD_AD9850 FUNCTION DEFINATION
---------------------------------------------------------------------------------------------*/

void FRQ_UD_AD9850(void)
{
FQ_UD = 1;
Delay10TCY();
Delay10TCY();
FQ_UD = 0;
Delay10TCY();
Delay10TCY();
Delay10TCY();


}
 

hello,

don't use reset function,put Reset input of AD9850 to Gnd.
do you have pull up resistor on control lines portB ?
how do you check frequency output ?
sinus level output is 1v peak to peak !
but square output is >4.5V at high level.

- - - Updated - - -

hello,

don't use reset function,put Reset input of AD9850 to Gnd.
do you have pull up resistor on control lines portB ?
how do you check frequency output ?
sinus level output is 1v peak to peak !
but square output is >4.5V at high level.
 

hello,

don't use reset function,put Reset input of AD9850 to Gnd.
do you have pull up resistor on control lines portB ?
how do you check frequency output ?
sinus level output is 1v peak to peak !
but square output is >4.5V at high level.

- - - Updated - - -

Hi,

1 - I have tried without RESET but ok I shall remove the RESET function and connect it to GND.
2- I don't have pull up resistors on PORTB pins, do I need pull up resistors and if I do what values should they be?
3- I am checking sinus by connecting oscilloscope's center pin to Zout2 and ground pin to Zout1, but not seeing anything. I this is wrong way of testing then how should I test it?

You have been so patient and helpful so far and I deeply appreciate your help.. Please do some magic from there and make this think work and I shall be very happy man...

Regards,
Malik
 

hello,

1) OK to ground Reset pin, it's remove a possible problem.
2) 4,7K to pull to VCC +5V
3) NO, Sinus signal output is between Z1 and Ground !
you have a second sinus output on Z2 !
and square output on others ..

and you can add this amplifier to increase signal and deliver to low impedance output...
 

Attachments

  • Ampli_de_sortie_AD9850_LM6172.jpg
    Ampli_de_sortie_AD9850_LM6172.jpg
    96.4 KB · Views: 83

hello,

1) OK to ground Reset pin, it's remove a possible problem.
2) 4,7K to pull to VCC +5V
3) NO, Sinus signal output is between Z1 and Ground !
you have a second sinus output on Z2 !
and square output on others ..

and you can add this amplifier to increase signal and deliver to low impedance output...


I shall try this tonight and let you know first thing tomorrow morning, I thought PIC's pin can pull up to +5V, am I wrong in thinking that.

Thanks Paul

- - - Updated - - -

hello,

1) OK to ground Reset pin, it's remove a possible problem.
2) 4,7K to pull to VCC +5V
3) NO, Sinus signal output is between Z1 and Ground !
you have a second sinus output on Z2 !
and square output on others ..

and you can add this amplifier to increase signal and deliver to low impedance output...

However I did notice that you don't have pull up resistors on your PORTs..

- - - Updated - - -

hello,

1) OK to ground Reset pin, it's remove a possible problem.
2) 4,7K to pull to VCC +5V
3) NO, Sinus signal output is between Z1 and Ground !
you have a second sinus output on Z2 !
and square output on others ..

and you can add this amplifier to increase signal and deliver to low impedance output...

Hi Paul,

When you said control lines of PORTB, do you mean SDATA, W_CLCK and FQ_UD lines or some other lines?

Regards,

Malik
 

When you said control lines of PORTB, do you mean SDATA, W_CLCK and FQ_UD lines or some other lines?

Yes,for the control lines for AD9850.

There is a bit dedicated for use internal pull resistor on Port B
i didn't check what is the position of this bit after a Reset on YOUR microcontroler.
It's better to activate it, or by default, to add external 4,7K pull up .

On my application i use inside" Init_Hardware()" for a PIC18F46K22
WPUB=0x02 ; // any pin pull up
INTCON2bits.RPU=0;
but for AD9850 i use PortC, not PortB !
 

Yes,for the control lines for AD9850.

There is a bit dedicated for use internal pull resistor on Port B
i didn't check what is the position of this bit after a Reset on YOUR microcontroler.
It's better to activate it, or by default, to add external 4,7K pull up .

On my application i use inside" Init_Hardware()" for a PIC18F46K22
WPUB=0x02 ; // any pin pull up
INTCON2bits.RPU=0;
but for AD9850 i use PortC, not PortB !

Hi Paul,

Thanks for you reply, I have connected the pull up resistors and connected the RESET to GND. I am observing the output between ZOUT1 and GND (all as you prescribed). But call it my bad luck or inexperience nothing is happening.

I have decided to buy the PIC that you are using and build a new prototype board from parts in your project less the joy stick.. so I shall use the PIC18F46K22 with 10MHZ XTAL as you have used and try interfacing that.. two things one that you'll have more idea about my situation secondly it might just in first go.

Currently I am using PICDem 2 Plus board and seems like nothing is happening. If you have any better idea please let me know, but now I really want this thing to work....

Regards,
Malik
 

hello,



it MUST WORK with your PIC !

i tried your versus on my Pic18F46K22 ( i have no 18F4520 !)
and i did some change like:
add a tempo at the start of program to wait power On stabilisation
use of variable instead of constant for floating point..
use low frequency to check .. not direct to 4Mhz
and check other value in a loop..

i tried on PORTC ..OK
after i tried also on PORTB with same pins as you ... OK

But be carreful with ICSP pins !
on my versus i added 1K resistor between ICSP PINs and RB6 , RB7
to avoid conflicts! when permanent connection with ICSP

Code:
//https://www.edaboard.com/threads/289261/
// 5 juin 2013
// Test OK with PIC18F46K22 and use of PORTC to drive AD9850
// Test OK to drive AD9850 with PORTB *  isolate trouh 1K resistor from ICSP !!


// uncomment the under line to use PIC18F4520
//#define  PIC18F4520

#ifdef PIC18F4520
#include <p18f4520.h>
#include <delays.h>
#include <math.h>

#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config OSC=XT

#else

#include <p18f46k22_.h> 
#include <delays.h>
#include <ctype.h>
#include <portb.h>
#include <math.h>

#ifdef OSCILLATEUR_INTERNE
#pragma config FOSC = INTIO67, FCMEN = OFF, PLLCFG=OFF            // CONFIG1H
#else
#pragma config FOSC = HSMP, PLLCFG=ON, PRICLKEN=ON ,FCMEN=OFF
#endif
#pragma config IESO=OFF,PWRTEN=OFF,BOREN=OFF,WDTEN=OFF,CCP2MX=PORTC1
#pragma config PBADEN=OFF,T3CMX=PORTC0,P2BMX=PORTC0
#pragma config MCLRE=EXTMCLR,STVREN=OFF,LVP=ON,XINST=OFF,DEBUG=OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF                    // CONFIG5L
#pragma config CPB = OFF, CPD = OFF                                          // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF                // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF                            // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF            // CONFIG7L
#pragma config EBTRB = OFF   

#endif


// #define RESET_AD9850 LATBbits.LATB4 // Reset line NOT USED ..direct to Gnd
//#define AD9850_CONTROL_WORD 0x00 // 8 Byte zerosconstante replaced by variable
//#define AD9850_FREQUENCY 1000.0 //  constant replaced by variable
//#define AD9850_FREQUENCY_FACTOR 34.35973837 // replaced by variable

#define W_CLCK LATBbits.LATB6	// Clock line to clock in data --> 2 of AD9850 HCV-SR08
#define FQ_UD LATBbits.LATB7	// Frequency up date line ---> 3 of AD9850 HCV-SR08
#define SDATA LATBbits.LATB5 // Serial data line ---> 4 of AD9850 HCV-SR08

#define Byte unsigned char	// Define CHAR as Byte data type

/* test with PORTC
#define SDATA LATCbits.LATC4 // Serial data line
#define W_CLCK LATCbits.LATC3	// Clock line to clock in data
#define FQ_UD LATCbits.LATC5	// Frequency up date line
*/


/*----------------------------------------------------------------------------------------
This structure's variable will be defined in UNION to access 32bit data in chunks of 8bits
-----------------------------------------------------------------------------------------*/
struct DataBytes	
{
near Byte pv0;
near Byte pv1;
near Byte pv2;
near Byte pv3;
};


/*---------------------------------------------------------------------------------------
Since UNION's all variables point to the same storage location we define one variable 
to get the 32bit data so it is defined as LONG data type, and to put it out as 8bit word
we define DATABYTE STRUCTURE's variable and access each element at a time to access 8bits
at one time.
------------------------------------------------------------------------------------------*/
union //ByteLevelAccess	
{
near unsigned long TuningWord;
near struct DataBytes DDS;
}AD9850_Serial_Data;

/*------------------------------------------------------------------------------------------
CONTROL BYTE FOR AD9850 and float values
-------------------------------------------------------------------------------------------*/

unsigned char AD9850_CONTROL_WORD;
float AD9850_FREQUENCY =1000.0 ;  // 1KHz
float AD9850_FREQUENCY_FACTOR = 34.35973837; // 2^32 divided by 125MHz

/*---------------------------------------
Prototype declerations of the functions
----------------------------------------*/

void Init_AD9850(void);
void SendSerialDataByteToAD9850(unsigned char Data);
void AD9850_Charge_Freq(float Freq);
//void AD9850_DATA_IN_CLOCK(void);
//void AD9850_RESET(void);
void FRQ_UD_AD9850(void);
void Tempo(unsigned  long delai);


void Tempo(unsigned  long delai)
{
while(delai-->0) ;

}
/*--------------------------------------------------------------------------------------------
MAIN FUCNTION
---------------------------------------------------------------------------------------------*/

void main()
{

ADCON1 = 0x0F; // All pins are now digital I/O
 ANSELB=0;
TRISB = 0;	// make all pin output
PORTB=0;

/*
... OK Working with PORTC
PORTC = 0x00;          
 ANSELC=0;
 TRISC = 0b10000000;    // RC0..RC6=Output 
  //TRISCbits.TRISC6 = 0;  // TX - UART1
 TRISCbits.TRISC7 = 1;  // RX - UART1
 PORTC=0;
 */

AD9850_CONTROL_WORD = 0; //initialize control word
SDATA=0;
W_CLCK=0;
FQ_UD=0;
// stabilisation delay for power up both PIC & AD9850
Tempo(250000);

AD9850_FREQUENCY =1000.0 ;  // 1KHz
AD9850_FREQUENCY_FACTOR = 34.35973837; // 2^32 divided by 125MHz

Init_AD9850();

Delay10KTCYx(100);

/*
AD9850_Serial_Data.TuningWord=68719;   // pour 2000 Hz  et 34360L pour 1000Hz
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv0);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv1);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv2);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv3);
SendSerialDataByteToAD9850(AD9850_CONTROL_WORD);
Delay10TCY();
FQ_UD = 1;
Delay10TCY();
FQ_UD = 0;
Delay10TCY();
*/

Tempo(2500000);

do
{

AD9850_FREQUENCY =1000.0 ;  // 1KHz
AD9850_Charge_Freq(AD9850_FREQUENCY);
Tempo(2500000);
AD9850_FREQUENCY =5000.0 ;  // 5KHz
AD9850_Charge_Freq(AD9850_FREQUENCY);
Tempo(2500000);
AD9850_FREQUENCY =10000.0 ;  // 10KHz
AD9850_Charge_Freq(AD9850_FREQUENCY);
Tempo(2500000);
AD9850_FREQUENCY =100000.0 ;  // 100KHz
AD9850_Charge_Freq(AD9850_FREQUENCY);
Tempo(2500000);
AD9850_FREQUENCY =1000000.0 ;  // 1MHz
AD9850_Charge_Freq(AD9850_FREQUENCY);
Tempo(2500000);
}
while(1);
}





/*-------------------------------------------------------------------------------------------
FUCNTION TO INITIALIZE THE AD9850 FOR SERIAL DATA INPUT
--------------------------------------------------------------------------------------------*/


void Init_AD9850(void)
{
Byte counter;

//initialize CLOCK,FRQ_UPDATE and SERIAL DATA lines with zero
//------------------------------------------------------------
SDATA=0;
W_CLCK=0;
FQ_UD=0;

//------------------------------------------------------------

//Reset address pointer to W0 (first word) in AD9850 
FQ_UD = 1;
Delay10TCY();
Delay10TCY();
FQ_UD = 0;
Delay10TCY();

W_CLCK = 1;         //1ere 
Delay10TCY();
W_CLCK = 0;
Delay10TCY();

//Enable serial mode
FQ_UD = 1;
Delay10TCY();
Delay10TCY();
FQ_UD = 0;
Delay10TCY();

// Following loop sends zero three times to AD9850 as W32=0,W33=0 & W34=0
counter=0;

do
{
SDATA = 0; 
W_CLCK = 1;	
Delay10TCY();
W_CLCK = 0;
Delay10TCY();
counter++;
}while (counter<3);
//Reset the control word pointer to W0 in AD9850
FQ_UD = 1;
Delay10TCY();
Delay10TCY();
FQ_UD = 0;
Delay10TCY();
}

/*--------------------------------------------------------------------------------------------
AD9850_Charge_Freq FUNCTION DEFINATION	
---------------------------------------------------------------------------------------------*/

void AD9850_Charge_Freq(float Freq)
{
AD9850_Serial_Data.TuningWord = (long) (Freq * AD9850_FREQUENCY_FACTOR);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv0);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv1);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv2);
SendSerialDataByteToAD9850(AD9850_Serial_Data.DDS. pv3);
SendSerialDataByteToAD9850(AD9850_CONTROL_WORD);
Delay10TCY();
FQ_UD = 1;
Delay10TCY();
Delay10TCY();
FQ_UD = 0;
Delay10TCY();
}


/*--------------------------------------------------------------------------------------------
SendSerialDataByteToAD9850 FUNCTION DEFINATION	
---------------------------------------------------------------------------------------------*/

void SendSerialDataByteToAD9850(unsigned char Data)
{
Byte counter = 0;

do
{
SDATA = 0;

if(Data & 0x01) SDATA=1; // Check LSB bit

Data = Data>>1; // RIGHT SHIFT THE DATA BY ONE BIT
W_CLCK = 1;	
Delay10TCY();
W_CLCK = 0;
Delay10TCY();
counter++;
}while(counter<8);

}
 

hi Paul,

Thanks for taking time and verifying the code I really appreciate.
Now since I have just copy pasted you code in to MPLAB and C18, its coming up with following error if I enable p18f4520.h

"P:\AD9850 DDS Project\V_1.1\Main.c:123:Error [1105] symbol 'ANSELB' has not been defined"

and if I try to p18f46k22.h is comes with following errors

P:\AD9850 DDS Project\V_1.1\Main.c:32:Error [1224] configuration setting 'FOSC' not recognized
P:\AD9850 DDS Project\V_1.1\Main.c:34:Error [1224] configuration setting 'PWRTEN' not recognized
P:\AD9850 DDS Project\V_1.1\Main.c:35:Error [1224] configuration setting 'T3CMX' not recognized
P:\AD9850 DDS Project\V_1.1\Main.c:36:Error [1225] configuration value 'EXTMCLR' not recognized for configuration setting 'MCLRE'

Am I doing something wrong or are you using some different version of C18 compiler.

Regards,
Malik
 

hello


maybe ANSELB belong only for 18F46K22 not for 18F4520
so, comment this pat of code

I am using MPLLAB IDE 8.91 (the last one) and MC18 V3.44
=> Language tool versions: mpasmwin.exe v5.47, mplink.exe v4.45, mcc18.exe v3.44, mplib.exe v4.45

dif you change the type of microcontoler in MPLAB settings ?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top