News:

;) This forum is the property of Proton software developers

Main Menu

Program for AD9833 Programmable Waveform Generator

Started by GDeSantis, Nov 29, 2021, 07:30 PM

Previous topic - Next topic

GDeSantis

The attached Positron program is designed to control the AD9833 Programmable Waveform Generator.  It is an example only and provides the following outputs:

    Sine Wave at 400 Hz
    Sine Wave at 1 KHz
    Triangular Wave at 400 Hz
    Square Wave at 200 Hz

For those interested in using the AD9833, please consult the device datasheet and application note AD-1070 for more information.  Links that provide additional information are noted below.

https://www.youtube.com/watch?v=YKY8q96JEuw
https://www.youtube.com/watch?v=Q_tzrksIEs8

Colin G3YHV

Great code  - I have used the AD9833 a few times in radio transmitters
at frequencies up to 10 MHz -  a very useful and cheap chip!
Your code looks a lot nicer than mine .Thanks
Colin G3YHV

streborc

Many thanks to GDeSantis this thread who got me kick-started with using the AD9833.

I have found the AD9833's spec sheet and its companion AN-1070 rather poorly written and confusing.  Much can be clarified with the following:

Writing the the AD9833's configuration registers is accomplished with 16 bit values that combine the 2-bit register address and a 14-bit register value.  There are 5 configuration registers with the following addresses in the 2 MSB positions:

MSB - - - - - - - - - - - - - LSB
0 0 c c c c 0 c c c c 0 c 0 c 0        Control Register
0 1 f f f f f f f f f f f f f f        Frequency 0 Register
1 0 f f f f f f f f f f f f f f        Frequency 1 Register
1 1 0 x p p p p p p p p p p p p          Phase 0 Register (uses a 3rd address bit)
1 1 1 x p p p p p p p p p p p p          Phase 1 Register (uses a 3rd address bit)

Equations are provided in the spec sheet for calculating the frequency and phase values.

      Freq_Reg = (Fout x 2^28)/Fclk   and  Phase_Reg = (Phase/2*pi) x 4096

For example, if the desired Fout is 100KHz, the Freq_Reg value is decimal 1073742 which converts to 0x10624E.  If the desired phase is 180 degrees (= pi radians), the Phase_Reg value is decimal 2048 which converts to 0x0800.

Converting these hexadecimal results into the correct register values can be a bit mind-bending, but here are the equation short-cuts:

Freq_Reg_0_LSB = (Freq_Reg & 0x3FFF) + 0x4000
Freq_Reg_0_MSB = (Freq_Reg/0x4000) + 0x4000

Freq_Reg_1_LSB = (Freq_Reg & 0x3FFF) + 0x8000
Freq_Reg_1_MSB = (Freq_Reg/0x4000) + 0x8000

For the 100KHz value 0x10624E, the register entries are:

Freq_Reg_0_LSB = (0x10624E & 0x3FFF) + 0x4000 = 0x224E + 0x4000 = 0x624E
Freq_Reg_0_MSB = (0x10624E/0x4000) + 0x4000 = 0x0041 + 0x4000 = 0x4041

If the 100KHz frequency is loaded into Freq_Reg_1, the values are instead:

Freq_Reg_0_LSB = (0x10624E & 0x3FFF) + 0x8000  =  0x224E + 0x8000 = 0xA24E
Freq_Reg_0_MSB = (0x10624E/0x4000) + 0x8000  = 0x0041 + 0x8000 = 0x8041

And, for example for phase, if the 100KHz frequency needs to be shifted 180 degrees, the Phase Register values are:

Phase_Reg_0 = Phase_Reg + 0xC000 = 0x0000 + 0xC000 = 0xC000 (for 0 degrees)
Phase_Reg_1 = Phase_Reg + 0xE000 = 0x0800 + 0xE000 = 0xE800 (for 180 degrees)

With different frequency values set in the two frequency registers, or with different phase values set in the two phase registers, FSK or PSK modulation can be implemented by writing to the control word, alternately selecting the registers.  The following code snippet illustrates the frequency values for 100KHz and 120KHz and the phase values 0 degrees and 180 degrees being set, and then FSK and PSK occurring for 10 cycles of each modulation type.

'Set Frequency and Phase Registers
'==============================================================================
' DAT = uC port assigned to SPI data
' CLK = uC port assigned to SPI clock
' CS = uC port assigned to SPI chip select
' Trig = uC port assigned to Oscilloscope trigger

 CS = 0 : DelayMS 1                         'Select AD9833
    SHOut DAT, CLK, 5, [$2100\16]           'Set Control Register & hold in reset
   
    SHOut DAT, CLK, 5, [$624E\16]           'Set Freq Register 0 LSB (100KHz)
    SHOut DAT, CLK, 5, [$4041\16]           'Set Freq Register 0 MSB
   
    SHOut DAT, CLK, 5, [$A92A\16]           'Set Freq Register 1 LSB (120KHz)
    SHOut DAT, CLK, 5, [$804E\16]           'Set Freq Register 1 MSB
   
    SHOut DAT, CLK, 5, [$C000\16]           'Set Phase Register 0 = 0 degrees
    SHOut DAT, CLK, 5, [$E800\16]           'Set Phase Register 1 = 180 degrees
   
    SHOut DAT, CLK, 5, [$2000\16]           'Release Reset
 CS = 1 : DelayMS 1
   
'Output Phase Modulation of Freq Register
'------------------------------------------------------------------------------   
Phase_Mod:
 i = 0                                     'Reset loop counter                                       
 CS = 0 : DelayMS 1                        'Select AD9833
 For i = 1 To 10
    SHOut DAT, CLK, 5, [$2000\16]          'Choose Phase Register 0
    High Trig                              'Scope trigger pulse
    DelayMS 500                            'Hold phase at 0 for 500 msec
   
    SHOut DAT, CLK, 5, [$2400\16]          'Choose Phase Register 1
    Low Trig                               'Scope trigger pulse                         
    DelayMS 500                            'Hold phase At 180 For 500 msec
 Next i
 CS = 1 : DelayMS 1                        'De-select AD9833
 
'Output Frequency Modulation of Phase Register
'------------------------------------------------------------------------------ 
Freq_Mod:
 i = 0                                     'Reset loop counter                                               
 CS = 0 : DelayMS 1                        'Select AD9833
 For i = 1 To 10
    SHOut DAT, CLK, 5, [$2000\16]          'Choose Freq Register 0
    High Trig                              'Scope trigger pulse
    DelayMS 1000                           'Hold frequency at 100KHz for 1000 msec
   
    SHOut DAT, CLK, 5, [$2800\16]          'Choose Freq Register 1
    Low Trig                               'Scope trigger pulse                         
    DelayMS 1000                           'Hold frequency at 120KHz For 1000 msec
 Next i
 CS = 1 : DelayMS 1                        'De-select AD9833
 
GoTo Phase_Mod                                                 
;-------------------------------------------------------------------------------