The main aim of this post is to write down my experiences while I’m working with DDS, Bus pirate and Arduino; sharing my experiences with you. In other hand, I’m trying to get an experience with this devices in order to build some good application. I’m aware there are some good code out there  but as sensei teach me once: the own experience is better than learn from others experience.

As every time I start a path I don’t know how long that takes me, so I’m not sure if there must be new chapters for this post or when can be publish. I hope soon.

The DDS: AD9837

A DDS is an oscillator controlled by a fixed and very stable master clock. A DDS has a ROM that stores the desired waveform for the output, mainly a sine shaped waveform. programming an internal divider is possible to set how many divisions we can get from the ROM shape, getting a wide amount of frequency values from this stored waveform. That’s in short. More information is suitable on the Wikipedia.

The AD9837 is a cheap, small but powerfull DDS circuit. I get a couple of samples from Analog Devices for free, but I get some problems with SMD soldering such a tinny circuit, so I decided to buy an Evaluation Board to check the function of the DDS. I found that this Evaluation is very expensive compared with the cost of a single AD9837, but this has been the most suitable solution to get my hands working with it.

The AD9837 has 10 pins (you can download the datasheet from ADI: here ). The programming of the chip is done by three pins with a SPI interface. According the Data sheet, with the Master Clock runnig at 16MHz, a resolution of 0.06Hz can be achieved. That’s a great resolution and I feel that if there’s any problem with the frequency it should be a Master clock problem, not the DDS.

The frequency register for the divider is 28 bit wide and the frequency output is:

freq = divider x frq_m_clk/2²⁸

Where divider must be in the range of:             0   ~    2²⁸ -1

For further information about how the AD9837 works read the Data Sheet carefully. I also recomend the reading of Aplication Notes AN-1070 to know how to program the device.

Bus Pirate and DDS

When the line CS is held low, the DDS samples the MOSI line every falling edge on CLK signal. That means that the Serial Data in MOSI line must be stable, while CLK line is falling. To achieve the MOSI stability, the SDATA will be placed on every CLK rising edge.

Let’s start with an example.

To program DDS the Bus Pirate should be configurated, as follows

HiZ>m5
Set speed:
 1. 30KHz
 2. 125KHz
 3. 250KHz
 4. 1MHz

(1)>2
Clock polarity:
 1. Idle low *default
 2. Idle high

(1)>2
Output clock edge:
 1. Idle to active
 2. Active to idle *default

(2)>2
Input sample phase:
 1. Middle *default
 2. End

(1)>1
CS:
 1. CS
 2. /CS *default

(2)>2
Select output type:
 1. Open drain (H=Hi-Z, L=GND)
 2. Normal (H=3.3V, L=GND)

(1)>2

Writting the command:

W  [0x01 0x00 0x21 0x00 0x5e 0xb8 0x40 0x14 0xc0 0x00 0x20 0x00]

the DDS output is set to 20kHz.

The DDS Data is 16 bit long, but Bus Pirate can’t do the job in that way. To achieve a 16-bit word we place two 8bit bytes together and send both with highest byte first, because DDS is using a MSB first method. Important is to hold CS at low level while both bits are sent. The CS line should be low until the last of 16 bits are sent. Is possible, as well, to send multiple words in the same CS low cycle. That’s what is done in our former example.

The left square bracket “[” starts driving low the CS line. Then 6 words are sent splited in two Bytes each one. The right square bracket “]” ends the CS cycle and recovers the high state for that line. So, the setup should be done with the following command, as well:

W [0x01 0x00][0x21 0x00][0x5e 0xb8][0x40 0x14][0xc0 0x00][0x20 0x00]

The “W” heading the command just powers up the DDS using Bus Pirate inner regulator.

The programming words get the following meaning:

0x0100: Reset the output.
0x2100: Output setup; full 2-word programming setup; keeps the reset.
0x5eb8: LSB of word for frequency divider.
0x4014: MSB of word for frequency divider.
0xc000: Phase programming word.
0x2000: Exits the reset state and enables the new frequency.

To program different frequencies is convenient to get a piece of code to generate the diferent values for frequency divider, in any language you want.

I wrote a PYTHON programm to help me whith it:

#!/usr/bin/python
# -*- encoding:utf-8 -*-

def calcula(mclk, freq, bitsdiv=28):
   div=2**bitsdiv
   return (freq*div/mclk)

def entra_freq():
   freq=input('Set the out DDS frequency: ')
   return freq

def main():
   lliura_trama()

def lliura_trama():
   freq=entra_freq()
   valor=calcula(16000000,freq, 28)
   MSB=valor/(2**14)
   LSB=valor%(2**14)
   #---------
   CR1_1=0x21
   CR1_0=0X00
   #---------
   PR1_1=0xc0
   PR1_0=0X00
   #---------
   CR2_1=0x20
   CR2_0=0X00
   #---------
   FR0_Mask=0x4000
   FR0_MSB=MSB | FR0_Mask
   FR0_LSB=LSB | FR0_Mask
   #--
   FR0_MSB1=FR0_MSB/256
   FR0_MSB0=FR0_MSB%256
   #--
   FR0_LSB1=FR0_LSB/256
   FR0_LSB0=FR0_LSB%256
   trama= "W [{0:#04x} {1:#04x} {2:#04x} {3:#04x} {4:#04x} {5:#04x} {6:#04x} {7:#04x} {8:#04x} {9:#04x}]".format(CR1_1, CR1_0, FR0_LSB1, FR0_LSB0, FR0_MSB1, FR0_MSB0, PR1_1, PR1_0, CR2_1, CR2_0)
   print trama

if __name__=="__main__":
   main()
Anuncios