Simple AD9850 DDS


The Analog Devices AD9850 is a CMOS, 125 MHz complete direct digital synthesiser on a single chip. It uses a single 5 V or 3.3 V supply, and with a 125 MHz clock, can generate a low-distortion sine wave or a square wave, from under 1 Hz up to about 60 MHz, with a tuning resolution of 0.0291 Hz. Full data on the device is available from ADI's web site:

http://www.analog.com/

Here is the schematic of a simple direct digital synthesiser using the AD9850, controlled by the PC printer port. It was built "ugly" style on a scrap of single-sided PCB material approx. 65 mm by 75 mm, with the AD9850 mounted on a little PCB adaptor, to make things easy. I didn't have the recommended 50R and 25R resistors for the DAC outputs, and used 47R and 27R values.

For simplicity, I'm using the serial mode for configuring the AD9850, clocking a 40-bit serial data stream into the device using the D0 and D1 lines of the PC printer port (a 32-bit frequency tuning word and an 8-bit control byte defining the phase modulation, power-down enable and control bits). When the configuration has been loaded, the D2 line is pulsed high, updating the output frequency.

Your printer port probably won't meet the CMOS input spec. for the 9850, for the logic high voltage level. Mine doesn't, but it worked OK. I subsequently added a 74HCT244 buffer to my prototype. Pull-up resistors should work, also. You don't really need the reset connection, as the 9850 is reset automatically when powered.

I used a 25 MHz clock, as I happened to have some 25 MHz oscillator modules handy. I am using a 10 MHz 5-element LP filter on the output. With this type of ugly construction, you are very unlikely to be able to use the maximum frequency of 125 MHz, although 75 MHz should be achievable using careful construction, suitable for all the HF amateur bands. Of course, you can use a micro-controller such as a PIC to control the device. With only three outputs required, you will have plenty of I/O left for interfacing a keypad and/or rotary encoder and an LCD or LED display.

The AD9850 comes in a 28-lead surface-mount SSOP package with .65 mm lead spacing, and is a rather awkward device for home construction. I have designed a little 27 mm by 34 mm adaptor PCB for it, which brings the leads out to .05" staggered pads.

Here are a few applications that come to mind for the AD9850:

Charlos, PA3CKR, uses the AD9850 on one of my adapters as the basis for a simple signal generator.

Here is a simple C program for controlling the AD9850, allowing direct frequency entry via the PC keyboard. It was written for the DJGPP DOS port of the FSF gcc compiler.

/* dds2.c - program to configure AD8750 via the PC printer port */


/*
** Port bit 0 - DATA
** Port bit 1 - W_CLK
** Port bit 2 - FQ_UD
** Port bit 3 - RESET
*/


#include <stdio.h>
#include <PC.H>
#include <math.h>


#define PORT 0x378


main()
{
	int i;
	float clock_in;
	float F_out;
	unsigned int delta_phase;


	/* set all pins low */
	outportb(PORT, 0x00);


	/* get clock frequency from user */
	printf("Clock frequency? ");
	scanf("%f", &clock_in);


	/* main program loop */
	for (;;)
	{
		/* get output frequency from user, abort if -ve */
		printf("\n\nOutput frequency? ");
		scanf("%f", &F_out);
		if (F_out < 0.0)
			exit(0);


		/* calculate AD9850 32-bit tuning word */
		delta_phase = (F_out * pow(2, 32)) / clock_in;


		/* output bit stream to AD9850 */
		tuning_word_out(delta_phase);


		/* output control byte */
		byte_out(0x00);


		/* latch frequency data - pulse FQ_UD high */
		outportb(PORT, 0x04);
		outportb(PORT, 0x00);
	}
}


/* output byte, MSB first */
byte_out(byte)
unsigned char byte;
{
	int i;


	for (i = 0; i < 8; i++)
	{
		if ((byte & 1) == 1)
			one();
		else
			zero();
		byte = byte >> 1;
	}
}


/* output 32-bit tuning word, MSB first */
tuning_word_out(tuning_word)
unsigned int tuning_word;
{
	int i;


	for (i = 0; i < 32; i++)
	{
		if ((tuning_word & 1) == 1)
			one();
		else
			zero();
		tuning_word = tuning_word >> 1;
	}
}


/* output a '1' to AD9850 */
one()
{
	outportb(PORT, 1);/* CLOCK low and DATA high - 01 */
	outportb(PORT, 3);/* CLOCK and DATA high - 11 */
	outportb(PORT, 0);/* CLOCK low and DATA low - 00 */
}


/* output a '0' to AD9850 */
zero()
{
	outportb(PORT, 0);/* CLOCK low and DATA low - 00 */
	outportb(PORT, 2);/* CLOCK high and DATA low - 10 */
	outportb(PORT, 0);/* CLOCK low and DATA low - 00 */
}


Comments/plaudits/brickbats to: leon_heller@hotmail.com

Return to Leon's home page: http://www.geocities.com/SiliconValley/Code/1835/index.html

Hosting by WebRing.