Page 1 of 3

AD 9832 DDS

Posted: 22 Jan 2007 21:27
by Copy'nPaste
Has anyone have a snippet of code for me on how to speak to this device?
I just can't seem to get my head around this concept :oops:
It has a serial interface, looks more like I2C to me, or SPI :?

Posted: 23 Jan 2007 04:45
by xor
SPI will work. You only need to write using SCLK and SDO on the PIC. You will need a 3rd pin of the PIC to operate FSYNC, which informs the device that data is being clocked in. The serial timing diagrams are pretty good to show the order and sequence of highs/lows to get commands and data into the device.

Posted: 23 Jan 2007 13:39
by Copy'nPaste
Still no luck, and it looked so simple to use :oops:

Posted: 23 Jan 2007 18:08
by Copy'nPaste
Don't ya just hate it when a manufacturer is unable to admit that someone else got it right, and they didn't?
So why didn't Analogue Devices just go with something like I2C?
It seems I'm going to need some bit banging waaay beyond my abilities to speak to this damn AD9832, if I use mikroElektronika Basic.
What might just work is the "Shift Out" function in Pic Basic Pro,
Why?, well the high/low transition relationship between the clock pulse and data byte seems to be important :-(, and in PBP I can change it, hint, hint :-)
I'd be really gratefull to be shown I'm wrong here, or that I've blown up the DDS somehow.
And I so wanted not ever to use PBP again :-(

Posted: 24 Jan 2007 05:42
by Copy'nPaste
Ok, with Spi_Init_Advanced, I can change a few parameters, but now for the next question, how do I shift in six blocks of 16bit data?

Posted: 24 Jan 2007 18:58
by Copy'nPaste
Nobody used these devices before?
I'm close to believing I might have blown uo the DDS, scoping out the data lines, the digital side seems in order.
The only pic code I find is assembler :evil:

Posted: 25 Jan 2007 04:50
by xor
GroundPounder wrote:Ok, with Spi_Init_Advanced, I can change a few parameters, but now for the next question, how do I shift in six blocks of 16bit data?
I have no doubt that a PIC and mikroBasic can make it work....believe me.... :D

Are you sure about 6 x 16 bits? If so, you can do SPI_Write() 12 times in a row, or 12 x 8 bits. You can also set up a subroutine with data arguments to take care of this.

Code: Select all

dim data as word[6]

sub procedure DDS_Write(dim byref data0 as word[6])
dim temp as byte
   For temp = 0 to 5
      SPI_WRITE(Hi(data0[temp])
      SPI_WRITE(data0[temp])
   Next temp
end sub

Posted: 25 Jan 2007 07:10
by Copy'nPaste
Yep, it requires a 32 bit word for frequency, 8 bits at a time, and then 2 x 16 bit control words, 8 bits at a time.
Rather challenging for me at this point, but I'm getting something out at this point, just not what I thought I told it to do.

Posted: 25 Jan 2007 09:31
by Copy'nPaste
So simple :oops:
For those that need a basic :) building block.....


Code: Select all

program meBasicAD9832ver1

        dim hmsb, hlsb, lmsb, llsb as byte

        sub procedure ddswrite
        TRISC = TRISC and $FD
            Spi_Init
            ClearBit(PORTC,1)             'Sync low enable write
            Spi_Write($F8)                'Setup AD9832 for writing
            Spi_Write($00)                'Just padding.......
            Spi_Write($33)                'Write High MSB into register $33
            Spi_Write(hmsb)
            Spi_Write($22)                'Write Low MSB into register $22
            Spi_Write(hlsb)
            Spi_Write($31)                'Write High LSB into register $31
            Spi_Write(lmsb)
            Spi_Write($20)                'Write Low LSB into register $20
            Spi_Write(llsb)
            Spi_Write($C0)                'Enable AD9832 for transmit
            Spi_Write($00)'               'Just padding.......
            SetBit(PORTC,1)               'Sync high disable write
            end sub
main:
'     while true
     
        hmsb = 4
        hlsb = 0
        lmsb = 0
        llsb = 0
        
        ddswrite

'        wend
  end.

Posted: 25 Jan 2007 13:33
by xor
As a suggestion, you only need to do SPI_INIT once in your program, in the beginning at startup would be fine.

Posted: 25 Jan 2007 14:54
by Copy'nPaste
Warren, don't you ever sleep? :)

Posted: 25 Jan 2007 15:05
by xor
Only when I'm not awake... :shock:

Posted: 01 Feb 2007 18:24
by Copy'nPaste
Haven't done much on this project lately, just confirmed I'm an idiot :(
SPI is WAY faster than I2C.
Sorry Analogue Devices :oops:

Anyone else played lately ?

Posted: 05 Mar 2007 20:04
by Copy'nPaste
Thanks to Sorcerer, and Xor, in alphabetical order :) ,
I have made this project work :D
Crude, but it works.
Thanks guys!

Posted: 13 Mar 2007 20:30
by Copy'nPaste
Refined this a bit, thanks a mil to those, knowingly and unknowingly, that pointed me in the right direction.
If this does help, please drop me a note?

Code: Select all

' A simple program to enable KeyPad control of an AD9832/9835 DDS
' 16X2 Lcd on Port B, DDS on Port C, KeyPad on Port D
' Default startup values in eeprom, 1 MHz out, for 24 MHz Clock
' Standard mikroElektronika connections as per EasyPic3 Board apply,
' using Pic 16F877A.
' RA0 switches display to frequency entry, RA1 changes clock value
' Both pins are normally pulled high, switches when pulled low
' KeyPad "*" deletes last keypress only, "#" writes new values to eeprom
' DDS PSEL0, PSEL1, FSELECT GROUNDED
' Hardware SPI function of Pic used
'
' MANY thanks to Sorcerer and Xor, who freely gives of their code....

program meBasicAD9832ver1
include "Print_Dec_16"      ' Xor's lcd print utility

        symbol delay50  = Delay_ms(50)
        symbol delay500 = Delay_ms(500)
        
        Dim frequency, xtal, cfreq, KeyInput,KeyInputOld as longint
        dim Key,Key1 as byte
        dim myvar as string[11]
        
        'Map 4*4 KeyPad to ascii
        const KeyPad as byte[16] = (49, 50, 51, 65,
                                    52, 53, 54, 66,
                                    55, 56, 57, 67,
                                    42, 48, 35, 68)
sub procedure Welcome  ' Welcome Message
    dim I as byte
    lcd_cmd(LCD_CURSOR_OFF)
    lcd_cmd(lcd_clear)
    lcd_out(1, 4, "gkSolutions")
    lcd_out(2,2,"DDS Synthesizer")
    For I = 0 to 3
    Delay500
    Next I
    lcd_cmd(lcd_clear)         ' Message Ends
end sub

sub function eread01(dim eeprom_addr, offset as byte) as longint
'    eeprom_addr = 0                'Is this nessary?
    For offset = 0 to 3
    FSR = @ frequency + offset
    INDF = EEPROM_READ(eeprom_addr + offset)
    Next offset
    result = frequency
    delay50
end sub

sub function eread02(dim eeprom_addr, offset as byte) as longint
'    eeprom_addr = 16
    For offset = 0 to 3
    FSR = @ xtal + offset
    INDF = EEPROM_READ(eeprom_addr + offset)
    Next offset
    result = xtal
    delay50
end sub

sub procedure lcdwrite01(dim yy as longint)
    Lcd_Cmd(LCD_CLEAR)       ' Clear display
    Lcd_Cmd(LCD_CURSOR_OFF)  ' Cursor off
'    print_dec(yy*16,"###.######",RJZ,myvar)         ' For FM Version
    print_dec(yy,"##.######",RJZ,myvar)            ' For Straight Version
     Lcd_Out(1, 4, "gkSolutions")
    Lcd_Out(2,3,myvar)
    Lcd_Out(2,13,"MHz")
    delay500
end sub

sub function CalcFreq(dim f, x as longint) as longint
    dim g as float
    g = ( f / x ) * $7FFFFFFF
    result = longint(g) * 2
    delay50
end sub

'sub procedure ddswrite(dim f as longint)     ' Hardware SPI, I HAD to play !
'    eread01(0, 0)
'    delay50
'    eread02(16, 0)
'    delay50
'    cfreq = CalcFreq(frequency, xtal)
'    delay50
'    TRISC = TRISC and $FD
'    ClearBit(PORTC,1)             'Sync low enable write
'    Spi_Write($F8)                'Setup AD9832 for writing
'    Spi_Write($00)                'Just padding.......
'    Spi_Write($33)                'Write High MSB into register $33
'    Spi_Write(highest(f))
'    Spi_Write($22)                'Write Low MSB into register $22
'    Spi_Write(higher(f))
'    Spi_Write($31)                'Write High LSB into register $31
'    Spi_Write(hi(f))
'    Spi_Write($20)                'Write Low LSB into register $20
'    Spi_Write(lo(f))
'    Spi_Write($C0)                'Enable AD9832 for transmit
'    Spi_Write($00)                'Just padding.......
'    SetBit(PORTC,1)               'Sync high disable write
'    delay50
'    lcdwrite01(frequency)
'    delay50
'end sub

sub procedure ddswrite(dim f as longint)      ' Soft SPI, ditto :-)
    eread01(0, 0)
    delay50
    eread02(16, 0)
    delay50
    cfreq = CalcFreq(frequency, xtal)
    delay50
    TRISC = TRISC and $FD
    ClearBit(PORTC,1)                  'Sync low enable write
    Soft_Spi_Write($F8)                'Setup AD9832 for writing
    Soft_Spi_Write($00)                'Just padding.......
    Soft_Spi_Write($33)                'Write High MSB into register $33
    Soft_Spi_Write(highest(f))
    Soft_Spi_Write($22)                'Write Low MSB into register $22
    Soft_Spi_Write(higher(f))
    Soft_Spi_Write($31)                'Write High LSB into register $31
    Soft_Spi_Write(hi(f))
    Soft_Spi_Write($20)                'Write Low LSB into register $20
    Soft_Spi_Write(lo(f))
    Soft_Spi_Write($C0)                'Enable AD9832 for transmit
    Soft_Spi_Write($00)                'Just padding.......
    SetBit(PORTC,1)                    'Sync high disable write
    delay50
    lcdwrite01(frequency)
    delay50
end sub

sub procedure ewrite(dim xx as longint)
    Eeprom_Write(0, lo(xx))
    delay50
    Eeprom_Write(1, hi(xx))
    delay50
    Eeprom_Write(2, higher(xx))
    delay50
    Eeprom_Write(3, highest(xx))
    delay50
end sub

sub procedure ewrite2(dim xx as longint)
    Eeprom_Write(16, lo(xx))
    delay50
    Eeprom_Write(17, hi(xx))
    delay50
    Eeprom_Write(18, higher(xx))
    delay50
    Eeprom_Write(19, highest(xx))
    delay50
end sub

sub Procedure Need_Input01       'Original routine from Sorcerer
      Lcd_cmd(lcd_clear)
      Lcd_Out(1, 4, "Freq in MHz")
      Lcd_Out(2, 3, "Enter with #")
      Key1 = 0
      KeyInput=0
      KeyInputOld=0
    While Key1<>35                           ' Exit on #
      Key=0
      while Key = 0
      Key = Keypad_Released
      Wend
      Key1=KeyPad[Key-1]
      If Key1=42 Then                        '* = delete (last input only!)
      KeyInput=KeyInputOld
      End If
      If (Key1 > 47) and (Key1 < 58) then    '0-9 are added in, anything else ignored
      KeyInputOld = KeyInput
      KeyInput = KeyInput * 10
      KeyInput = KeyInput + Key1 - 48
      End If
'      print_dec(keyinput,"###.######",RJZ,myvar)    ' For FM Version
      print_dec(keyinput,"##.######",RJZ,myvar)    ' For Straight Version
      Lcd_cmd(LCD_CURSOR_OFF)
      Lcd_Out(2, 1,"                ")
      Lcd_Out(2, 4, myvar)
      delay50
    Wend
'        KeyInput = KeyInput div 16              ' Only For FM Version
        ewrite(Keyinput)
        delay50
        ddswrite(cfreq)          ' Can't explain why it needs TWO writes ?
        delay50
        ddswrite(cfreq)
        delay50
end sub

sub Procedure Need_Input02                       ' Fine Tune xtal Osc
      Lcd_cmd(lcd_clear)
      Lcd_Out(1, 1, "Xtal Freq in MHz")
      Lcd_Out(2, 3, "Enter with #")
      Key1 = 0
      KeyInput=0
      KeyInputOld=0
    While Key1<>35                           ' Exit on #
      Key=0
      while Key = 0
      Key = Keypad_Released
      Wend
      Key1=KeyPad[Key-1]
      If Key1=42 Then                        '* = delete (last input only!)
      KeyInput=KeyInputOld
      End If
      If (Key1 > 47) and (Key1 < 58) then    '0-9 are added in, anything else ignored
      KeyInputOld = KeyInput
      KeyInput = KeyInput * 10
      KeyInput = KeyInput + Key1 - 48
      End If
      print_dec(keyinput,"##.######",RJZ,myvar)
      Lcd_cmd(LCD_CURSOR_OFF)
      Lcd_Out(2, 1,"                ")         ' Cleans Line for next display
      Lcd_Out(2, 4, myvar)
      delay50
    Wend
        ewrite2(Keyinput)
        delay50
        ddswrite(Cfreq)             ' Can't explain why it needs TWO writes ?
        delay50
        ddswrite(Cfreq)
        delay50
end sub

main:
       ADCON1 = 7
       trisa = %11111111
'       Spi_Init                            ' Required for Hardware SPI
       Soft_Spi_Config(PortC,4, 5, 3)       ' Required for Soft_SPI
       Lcd_Init(PORTB)
       Keypad_Init(PORTD)
       Welcome
       ddswrite (cfreq)
       delay50
       ddswrite(cfreq)
       delay50
eloop:
       if porta.0 = 0 then
       Need_Input01
       end if
       if porta.1 = 0 then
       Need_Input02
       end if
goto eloop
end.