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
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);
}
is it a Quartz or External oscillator ?I am using external 4MHz oscillator
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]
}
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] }
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…
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.
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...
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...
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...
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 !
//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);
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?