Author Topic: programming a pic for ad9850  (Read 12752 times)

0 Members and 1 Guest are viewing this topic.

Offline matiseTopic starter

  • Contributor
  • Posts: 28
programming a pic for ad9850
« on: November 14, 2013, 04:43:48 pm »
Hi :)
My first post on this nice forum.
I got one of this ad9850 dds-card from china.
But there is no good programming examples out there that i can use.
I want to try to get it running on 3.6 MHz...

If i got it right the clk needed = 3.5 ns (min)
And FQ = 7.0 ns. (min)
hex=075F6FD2  (3.6MHz)

And my header for this is:

#include <p18f1220.h>
#pragma config WDT=OFF , OSC=INTIO2 , PWRT=ON, LVP=OFF, MCLRE=OFF
#include <delays.h>

void main(void)
{
   //SET UP
   //OSCCON defaults to 31kHz. So no need to alter it.
   ADCON1 = 0x7F;        //All IO are digital or 0b01111111 in binary
   TRISA = 0b11111111;   //sets PORTA as all inputs
   PORTA = 0b00000000;   //turns off PORTA outputs
   TRISB = 0b00000000;   //sets PORTB as all outputs
   PORTB = 0b00000000;   //sets off PORTB outputs, good start position
   
   while(1)
   {
      
   freq = 075F6FD2;
      
      
      }
      }
      
I will try to programming this but i need some help.
Someone that can help me in right direction here?
Lets say data(hex) on RB 4
clk RB5
FQ RB6
thnx matise
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #1 on: November 14, 2013, 06:11:27 pm »
It is exceedingly simple:

1) write a routine to set/clear pins;
2) write a routine to send a byte by calling the routine in 1);
3) write a routine to send the control words by calling the routine in 2;
4) write a routine to decompose the desired frequency into control words;
5) write a routine to send the right control words associated with the desired frequency by calling routines in 3) and 4).

All you need is to implement each of the 5 steps and you are done.

================================
https://dannyelectronics.wordpress.com/
 

Offline Rufus

  • Super Contributor
  • ***
  • Posts: 2095
Re: programming a pic for ad9850
« Reply #2 on: November 14, 2013, 07:46:42 pm »
It is exceedingly simple:

It is moderately simple for someone who knows what they are doing. For someone who posts

 freq = 075F6FD2;

and asks what should go there instead it may be exceedingly difficult.

I suggest the OP searches the web harder, an example here http://www.ccsinfo.com/forum/viewtopic.php?p=155780 for instance.
 

Offline matiseTopic starter

  • Contributor
  • Posts: 28
Re: programming a pic for ad9850
« Reply #3 on: November 16, 2013, 09:18:47 am »
Tnx for the link. :)
I can see now that its not easy to programming a pic for that kind of task...
Its a more advanced c-programming than i know of when im programming sensors or lcd...  :)

I need to find the right book so i understand this better.
Anyone any suggestions?
Some pic-book or c-programming books that will cover what i need to learn to program this kind of dds?

tnx
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #4 on: November 16, 2013, 11:41:10 pm »
Quote
I can see now that its not easy to programming a pic for that kind of task...

I did a ad9850 based signal generation from a 16F684. As easy as 123.
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #5 on: November 16, 2013, 11:42:11 pm »
Quote
I need to find the right book so i understand this better.

1. take a decent class in C;
2. read manuals for your tools;
3. read the device datasheets.
4. code, code and then code some more.
================================
https://dannyelectronics.wordpress.com/
 

Offline Rufus

  • Super Contributor
  • ***
  • Posts: 2095
Re: programming a pic for ad9850
« Reply #6 on: November 17, 2013, 12:20:06 am »
Tnx for the link. :)
I can see now that its not easy to programming a pic for that kind of task...

It is only 34 lines of code - if you are inexperienced figuring out what it does would be as good a place as any to start to become more experienced.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #7 on: November 17, 2013, 02:13:23 am »
Agreed with Rufus.

Many times, people are held back from doing fancy stuff because they have no clue about the simpler stuff.
================================
https://dannyelectronics.wordpress.com/
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11695
  • Country: my
  • reassessing directives...
Re: programming a pic for ad9850
« Reply #8 on: November 17, 2013, 09:21:42 am »
   while(1) {
      freq = 075F6FD2;
   }
golden loop of eternity :palm: may i suggest LED blinker?
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline matiseTopic starter

  • Contributor
  • Posts: 28
Re: programming a pic for ad9850
« Reply #9 on: January 28, 2014, 06:08:42 pm »
i guess the idea should be something like this?

#include <p18f1220.h>
#pragma config WDT=OFF , OSC=INTIO2 , PWRT=ON, LVP=OFF, MCLRE=OFF
#include <delays.h>

#define data 10
#define clk  11
#define ud   12

unsigned long freq;
int count;

void main(void)
{
   //SET UP
   //OSCCON defaults to 31kHz. So no need to alter it.
   ADCON1 = 0x7F;        //All IO are digital or 0b01111111 in binary
   TRISA = 0b11111111;   //sets PORTA as all inputs
   PORTA = 0b00000000;   //turns off PORTA outputs
   TRISB = 0b00000000;   //sets PORTB as all outputs
   PORTB = 0b00000000;   //sets off PORTB outputs, good start position
   
   freq = 125413045;
   
   while(1)   
{
   for(count=0;count<32;count++)
   {
   
   PORTBbits.RB4 = 1;     // Data
   PORTBbits.RB4 = freq;

   
   PORTBbits.RB5 = 1;     // Clock
   PORTBbits.RB5 = 0;
   }
   
   PORTBbits.RB4 = 0;
   for(count=0;count<8;count++)  // 8 blank
   {
   PORTBbits.RB5 = 1;     // Clock
   PORTBbits.RB5 = 0;
   }
   
   PORTBbits.RB6 = 1;     // Ud
   PORTBbits.RB6 = 0;
   
   }
}
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #10 on: January 28, 2014, 06:41:51 pm »
-PORTBbits.RB4 = freq;-

not even in the same universe.
================================
https://dannyelectronics.wordpress.com/
 

Offline matiseTopic starter

  • Contributor
  • Posts: 28
Re: programming a pic for ad9850
« Reply #11 on: January 28, 2014, 07:39:11 pm »
lol, no i can understand that but i dont know how to "link" freg to data out...  :)

Rest of it should be something near.
I know that the dds want 32 bits, and the Clock give one pulse every loop.
then 8 blank and the Clock give pulses and finally ud...

Someone about that frequency-data output?

Or am i totally wrong with this?
 

Offline Rerouter

  • Super Contributor
  • ***
  • Posts: 4694
  • Country: au
  • Question Everything... Except This Statement
Re: programming a pic for ad9850
« Reply #12 on: January 28, 2014, 07:57:10 pm »
while this has a tiny bit of arduino style code in it i think it could help (if your programming in C, you should only have to point to the correct pins)

Code: [Select]
#define pulseHigh(pin) {bitSet(PORTD, pin); bitClear(PORTD, pin);} // for pulsing ad9850 pins

  // Initialises AD9850 Module
  pulseHigh(RESET);                  // AD9850 Setup
  pulseHigh(W_CLK);
  pulseHigh(FQ_UD);                  // this pulse enables serial mode - Datasheet page 12 figure 10
  sendFrequency (0);


// transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
void tfr_byte(byte data) {
  for (byte i=0; i<8; i++, data>>=1) {
    bitWrite(PORTD, 6, data & 0x01);        // Write data out of DATA pin
    pulseHigh(W_CLK);                       // after each bit sent, CLK is pulsed high
  }
}

/*-------------------------------------------------------------------------------------------------------*/
// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
// Steps in 0.02910383046hz
void sendFrequency(double frequency) {
  int32_t freq = frequency * 4294967295/125000000;  // converts Hz into Binary
  for (byte b=0; b<4; b++, freq>>=8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0x000);                                    // Final control byte, Includes Phase and power down
  pulseHigh(FQ_UD);                                   // Done!  Should see output
}
 

Offline mariush

  • Super Contributor
  • ***
  • Posts: 5071
  • Country: ro
  • .
Re: programming a pic for ad9850
« Reply #13 on: January 28, 2014, 08:23:19 pm »
Read the PIC datasheet.

Use the internal clock of the PIC and set it to some sane Mhz value .. for example 1 Mhz or 4 Mhz.  With PIC microcontrollers, everything works in sets of 4 cycles. Most instructions need 4 Hz to finish, some instructions need 2 x 4 Hz to finish. So at best, with 1 Mhz clock you have 250k instructions per second or 250 per ms or 2.5 per ns. With 4 Mhz, you have 1 million instructions per second or about 1000 per ms or 1 per nanosecond.

By default, I think the PIC will stay at 31 Khz and that's superslow. Just setting those RB3 and RB4 will take maybe a 10th of a second.

If i got it right the clk needed = 3.5 ns (min)
And FQ = 7.0 ns. (min)
hex=075F6FD2  (3.6MHz)

hex=075F6FD2  (3.6MHz)  is incorrect. 
To put a binary value in a variable, you say  binarynumber = 0b10101010;
To put a hexadecimal value in a variable, you say hex = 0x075F6FD2;

Since you're working with a 8 bit microcontroller, it may be easier for you to store that frequency as 4 separate bytes:  hex1 = 0x07; hex2 = 0x5F; hex3 = 0x67;  hex4 = 0xD2;
You can then write these into a .h file attached to your project, and then just use the function names to get a bit from the each byte:

    #define bit_get(var,bitno)   ((var) & (1 << (bitno)))
    #define bit_set(var,bitno)    ((var) |= 1 << (bitno))
    #define bit_clear(var,bitno)  ((var) &= ~(1 << (bitno)))

ex  PORTBbits.RB4 = bit_get(hex1,0);  <--- put on RB4 the first bit of hex1.


  PORTBbits.RBx  where x = 0 to 7 set the pins of the PORT B to 0 or 1 .. they're BITS.  You can only put 0 or 1 there. Can't assign a number like the whole frequency. You have to put one bit at a time, set the clock bit on and then off so that the dds takes the bit inside, then continue with the next bit.  You basically have to send 32 bits, one at a time.

Now here you have to remember those " clk needed = 3.5 ns (min) And FQ = 7.0 ns. (min) "  - if your clock is 4 mhz or something like that, when you put 1 on one of those  .RBx variables, you have to keep in mind each of those instructions may take less than 1-2 ns, so you may want to add some delays there to give the other chip time to process what you send to it.

You can add in the same .h file some helper functions like these:

#define delay_1tcy()    asm("nop")
#define delay_2tcy()    asm("goto $+1")

so when you say in your code  delay_1tcy();  the pic will waste one instruction doing nothing.  Again, at 4  Mhz, that's 1 megainstructions per second or 1000 per ms or 1 per ns. So the PIC waits for 1 ns.
If you have to make sure you wait at least 3.5ns, then add delay_2tcy(); twice.
 
Same for the 7ns minimum.

--

If this is too confusing, you should probably start with a simple blink led example code and move from there.

I suggest at least browsing through these documents:

MPLAB® XC8 Getting Started Guide : http://ww1.microchip.com/downloads/en/DeviceDoc/50002173A.pdf
MPLAB® XC8 C Compiler User’s Guide : http://ww1.microchip.com/downloads/en/DeviceDoc/MPLAB_XC8_C_Compiler_User_Guide.pdf

 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #14 on: January 28, 2014, 08:51:31 pm »
Quote
i dont know how to "link" freg to data out...

That's simple: the datasheet has it explained in great details.

Quote
while this has a tiny bit of arduino style...

A few issues:

1) I would have structured it so that you have a routine that sends the ad9850 a byte, another that sends the tuning word, and another that converts the desired frequency into the tuning word, plus one that reset the device / pins. This allows you considerable flexibility.

2)
Code: [Select]
pulseHigh(RESET);                  // AD9850 Setup
You probably don't want to reset the chip each time you try to change the output frequency.

3)
Code: [Select]
  int32_t freq = frequency * 4294967295/125000000;  // converts Hz into Binary
Probably the least elegant part of the code. You don't want to use floating point math; You want the code to be flexible with regards to master frequency used, etc.

They are ways to achieve all of that, entirely in integer math.

4)
Code: [Select]
    tfr_byte(freq & 0xFF);
The AND operation is unnecessary.

5)
Code: [Select]
  tfr_byte(0x000);                                    // Final control byte, Includes Phase and power down
Watch the prototype for tfr_byte.

Hope it helps.
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #15 on: January 28, 2014, 09:45:41 pm »
Quote
Use the internal clock of the PIC...

Are you sure that you are talking about the same thing?
================================
https://dannyelectronics.wordpress.com/
 

Offline mariush

  • Super Contributor
  • ***
  • Posts: 5071
  • Country: ro
  • .
Re: programming a pic for ad9850
« Reply #16 on: January 28, 2014, 10:05:02 pm »
Yes.

The code in his first post has these:

#include <p18f1220.h>
#pragma config WDT=OFF , OSC=INTIO2 , PWRT=ON, LVP=OFF, MCLRE=OFF
#include <delays.h>

void main(void)
{
   //SET UP
   //OSCCON defaults to 31kHz. So no need to alter it.


So he's using a PIC18F1220  which has an internal oscillator running at up to 8 Mhz but he leaves it at the default of 31 kHz ... this will make communicating with the ad9850 super slow.

later edit: oh, I may have expressed myself incorrectly. Yeah, there's no "clock", i meant internal oscillator.
« Last Edit: January 28, 2014, 10:13:23 pm by mariush »
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #17 on: January 28, 2014, 10:44:56 pm »
To change that, you can simply write to IRCFx bits - it takes no more than a line to do.
================================
https://dannyelectronics.wordpress.com/
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11695
  • Country: my
  • reassessing directives...
Re: programming a pic for ad9850
« Reply #18 on: January 28, 2014, 11:14:08 pm »
you are close! change this...
Code: [Select]
for(count=0;count<32;count++) {
   
    PORTBbits.RB4 = 1;     // Data
    PORTBbits.RB4 = freq;
   
    PORTBbits.RB5 = 1;     // Clock
    PORTBbits.RB5 = 0;
};

to this...
Code: [Select]
for(count=0;count<32;count++) {
   
    PORTBbits.RB4 = (freq & 1);   // Data
    PORTBbits.RB5 = 1;            // Clock
    freq >>= 1;

    PORTBbits.RB5 = 0;
};
you need additional storage to save freq value though since the loop will modify and zero it at "freq >>= 1;" when leaving the loop. keep up the hardwork!
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline matiseTopic starter

  • Contributor
  • Posts: 28
Re: programming a pic for ad9850
« Reply #19 on: January 29, 2014, 08:59:47 am »
thank you all very, very much for your help!
I will carefuly read your advices the coming weeks and try to get it right.
I Think your advices is what i needed.
I bought the same c-programming books they use in Universitys and ive almost finnished that, and also i bought pic-books and i now know simpler pic-programming.
The last weeks i learned about bit-programming and wrote a rotary encoder program for this dds...

   PORTAbits.RA0 = 1;    //till pin1
    PORTAbits.RA1 = 1;    //till pin2
    pin1 = PORTAbits.RA0;
    pin2 = PORTAbits.RA1;
   
    if(pin1==1)
    sum1 = 0x08;   // bit 3
   
    if(pin2==1)
    sum1 |= (1<<2);   // bit 2

    ny1 = PORTAbits.RA0;   // new encoder bits
    ny2 = PORTAbits.RA1;
   
    if(ny1 != pin1 || ny2 != pin2)  //if new encoder numbers
    {
    if(ny1==1)
    sum1 |= (1<<1);   // bit 1
   
    if(ny2==1)
    sum1 |= (1<<0);   // bit 0
   
    if(sum1 == 1 || sum1 == 7 || sum1 == 14 || sum1 == 8 ) freq =+1024;  //clockwise movement
    if(sum1 == 11 || sum1 == 13 || sum1 == 4 || sum1 == 2) freq=-1024;  //counter-clockwise movement

I hope it will work.
The problem is that i cant find any books that teach programming for this kind of stuff...
So i try to find "fragments"of info on the net...

Electronics takes time to learn and its really not easy.  :)
But i take it very seriously.

thanks again.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: programming a pic for ad9850
« Reply #20 on: January 29, 2014, 11:15:47 am »
Quote
The problem is that i cant find any books that teach programming for this kind of stuff..

Coding a mcu is largely the same as coding on PC: except that there are those special "memory regions" (="registers") that control peripheral activities.

So you need to a few things:
1) Being good at C.
2) Being able to understand the datasheet of the mcu;
3) Being able to understand the datasheet of the devices your mcu interacts with.

After that, it is a breeze.

Your trouble here is that you lacked even the most rudimentary understanding of ad9850.
================================
https://dannyelectronics.wordpress.com/
 

Offline matiseTopic starter

  • Contributor
  • Posts: 28
Re: programming a pic for ad9850
« Reply #21 on: February 02, 2014, 03:30:43 pm »
I understand now how (freq & 1) works.
About tuningword and it increase its number into the phase accumulator each time it receives a Clock pulse.
That builds up the sinwave...

But i cant find any info about this next line:
freq >>= 1;
What is this all about?
What it says is that it divide freq but why?
What is the purpose?
 

Offline mariush

  • Super Contributor
  • ***
  • Posts: 5071
  • Country: ro
  • .
Re: programming a pic for ad9850
« Reply #22 on: February 02, 2014, 04:05:36 pm »
freq >>=1  is the same thing as freq = freq >> 1 

which means shift the bits in freq to the right by 1 .. ex  10110101  becomes 01011010   or 181 becomes 90  (181/2)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf