A sine wave generator using AD9833 and AD9850 using STM32F103RB

Dependencies:   mbed

This is a sine wave generator using DDS IC' AD9833 and AD9850. The STM32F1 microcontroller produces the SPI commands for the two DDS.

Learn more about STM32F1 in my blog: https://www.teachmemicro.com

Committer:
roland_tmm
Date:
Tue Nov 21 19:18:25 2017 +0000
Revision:
2:602f7589c53e
Parent:
1:9dcccb399f0b
Edited comments/description;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
roland_tmm 0:6069c0f2a245 1 /******************************************************************************************************************
roland_tmm 2:602f7589c53e 2 * AD9850 library for AD9850
roland_tmm 0:6069c0f2a245 3 * Created 11/21/2017
roland_tmm 0:6069c0f2a245 4 * Roland Pelayo
roland_tmm 0:6069c0f2a245 5 *
roland_tmm 0:6069c0f2a245 6 * Use this library freely
roland_tmm 0:6069c0f2a245 7 *
roland_tmm 0:6069c0f2a245 8 * Hardware connections :
roland_tmm 0:6069c0f2a245 9 * W_CLK -> any pin
roland_tmm 0:6069c0f2a245 10 * FQ_UD -> any pin
roland_tmm 0:6069c0f2a245 11 * DATA/D7 -> any pin
roland_tmm 0:6069c0f2a245 12 * RESET -> any pin
roland_tmm 0:6069c0f2a245 13 *
roland_tmm 0:6069c0f2a245 14 * Functions :
roland_tmm 0:6069c0f2a245 15 * dds.begin(W_CLK pin, FQ_UD pin, DATA pin, RESET pin); Initialize the output pins and master reset the AD9850
roland_tmm 0:6069c0f2a245 16 * dds.calibrate(frequency); Compensation of crystal oscillator frequency
roland_tmm 0:6069c0f2a245 17 * dds.setfreq(frequency,phase); frequency in Hz, phase coded on 5 bits
roland_tmm 0:6069c0f2a245 18 * dds.down(); power down mode reducing the dissipated power from 380mW to 30mW @5V
roland_tmm 0:6069c0f2a245 19 * dds.up(); wake-up the AD9850
roland_tmm 0:6069c0f2a245 20 *
roland_tmm 0:6069c0f2a245 21 * AD9850 datasheet at http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf
roland_tmm 0:6069c0f2a245 22 *
roland_tmm 0:6069c0f2a245 23 *****************************************************************************************************************/
roland_tmm 0:6069c0f2a245 24
roland_tmm 0:6069c0f2a245 25 #include "AD9850.h"
roland_tmm 0:6069c0f2a245 26 #include "mbed.h"
roland_tmm 0:6069c0f2a245 27
roland_tmm 0:6069c0f2a245 28 #define W_CLK PB_10
roland_tmm 0:6069c0f2a245 29 #define FQ_UD PB_11
roland_tmm 0:6069c0f2a245 30 #define DATA PB_1
roland_tmm 0:6069c0f2a245 31 #define RESET PB_0
roland_tmm 0:6069c0f2a245 32
roland_tmm 0:6069c0f2a245 33 SPI SPI_dev2(DATA, PB_8, W_CLK);
roland_tmm 0:6069c0f2a245 34
roland_tmm 0:6069c0f2a245 35 DigitalOut wclk(W_CLK);
roland_tmm 0:6069c0f2a245 36 DigitalOut fq_ud(FQ_UD);
roland_tmm 0:6069c0f2a245 37 DigitalOut dat(DATA);
roland_tmm 0:6069c0f2a245 38 DigitalOut res(RESET);
roland_tmm 0:6069c0f2a245 39
roland_tmm 0:6069c0f2a245 40 AD9850::AD9850() {
roland_tmm 0:6069c0f2a245 41
roland_tmm 0:6069c0f2a245 42 }
roland_tmm 0:6069c0f2a245 43
roland_tmm 0:6069c0f2a245 44 void AD9850::Begin() {
roland_tmm 1:9dcccb399f0b 45 SPI_dev2.format(16,0);
roland_tmm 0:6069c0f2a245 46 deltaphase = 0;
roland_tmm 0:6069c0f2a245 47 phase = 0;
roland_tmm 0:6069c0f2a245 48 calibFreq = 125000000;
roland_tmm 0:6069c0f2a245 49 begin_priv();
roland_tmm 0:6069c0f2a245 50 }
roland_tmm 0:6069c0f2a245 51
roland_tmm 0:6069c0f2a245 52 void AD9850::begin_priv() {
roland_tmm 0:6069c0f2a245 53
roland_tmm 1:9dcccb399f0b 54 res = 0;
roland_tmm 1:9dcccb399f0b 55 wait_us(5);
roland_tmm 0:6069c0f2a245 56 res = 1;
roland_tmm 1:9dcccb399f0b 57 wait_us(5);
roland_tmm 0:6069c0f2a245 58 res = 0;
roland_tmm 0:6069c0f2a245 59
roland_tmm 1:9dcccb399f0b 60 wclk = 0;
roland_tmm 1:9dcccb399f0b 61 wait_us(5);
roland_tmm 0:6069c0f2a245 62 wclk = 1;
roland_tmm 1:9dcccb399f0b 63 wait_us(5);
roland_tmm 0:6069c0f2a245 64 wclk = 0;
roland_tmm 0:6069c0f2a245 65
roland_tmm 1:9dcccb399f0b 66 fq_ud = 0;
roland_tmm 1:9dcccb399f0b 67 wait_us(5);
roland_tmm 0:6069c0f2a245 68 fq_ud = 1;
roland_tmm 1:9dcccb399f0b 69 wait_us(5);
roland_tmm 0:6069c0f2a245 70 fq_ud = 0;
roland_tmm 0:6069c0f2a245 71
roland_tmm 0:6069c0f2a245 72 }
roland_tmm 0:6069c0f2a245 73
roland_tmm 0:6069c0f2a245 74 void AD9850::update() {
roland_tmm 0:6069c0f2a245 75 uint32_t d,p;
roland_tmm 0:6069c0f2a245 76 for (int i=0; i<4; i++, deltaphase>>=8) {
roland_tmm 1:9dcccb399f0b 77 d = ReverseBits(deltaphase);
roland_tmm 1:9dcccb399f0b 78 SPI_dev2.write((d>>16) & 0x000000FF);
roland_tmm 1:9dcccb399f0b 79 SPI_dev2.write(d & 0x000000FF);
roland_tmm 0:6069c0f2a245 80 // shiftOut(DATA, W_CLK, LSBFIRST, deltaphase & 0xFF);
roland_tmm 0:6069c0f2a245 81 }
roland_tmm 1:9dcccb399f0b 82 p = ReverseBits(phase);
roland_tmm 1:9dcccb399f0b 83 SPI_dev2.write((p>>16) & 0x000000FF);
roland_tmm 1:9dcccb399f0b 84 SPI_dev2.write(p & 0x000000FF);
roland_tmm 0:6069c0f2a245 85 //shiftOut(DATA, W_CLK, LSBFIRST, phase & 0xFF);
roland_tmm 1:9dcccb399f0b 86 fq_ud = 0;
roland_tmm 1:9dcccb399f0b 87 wait_us(5);
roland_tmm 0:6069c0f2a245 88 fq_ud = 1;
roland_tmm 1:9dcccb399f0b 89 wait_us(5);
roland_tmm 0:6069c0f2a245 90 fq_ud = 0;
roland_tmm 0:6069c0f2a245 91 }
roland_tmm 0:6069c0f2a245 92
roland_tmm 0:6069c0f2a245 93
roland_tmm 0:6069c0f2a245 94 void AD9850::SetDDSFrequency(double f, uint8_t p) {
roland_tmm 0:6069c0f2a245 95 deltaphase = f * 4294967296.0 / calibFreq;
roland_tmm 0:6069c0f2a245 96 phase = p << 3;
roland_tmm 0:6069c0f2a245 97 update();
roland_tmm 0:6069c0f2a245 98 }
roland_tmm 0:6069c0f2a245 99
roland_tmm 0:6069c0f2a245 100
roland_tmm 0:6069c0f2a245 101 void AD9850::down() {
roland_tmm 1:9dcccb399f0b 102 fq_ud = 0;
roland_tmm 1:9dcccb399f0b 103 wait_us(5);
roland_tmm 0:6069c0f2a245 104 fq_ud = 1;
roland_tmm 1:9dcccb399f0b 105 wait_us(5);
roland_tmm 0:6069c0f2a245 106 fq_ud = 0;
roland_tmm 1:9dcccb399f0b 107 SPI_dev2.write((ReverseBits(0x00000004))>>16);
roland_tmm 1:9dcccb399f0b 108 SPI_dev2.write(ReverseBits(0x00000004));
roland_tmm 0:6069c0f2a245 109 //shiftOut(DATA, W_CLK, LSBFIRST, 0x04);
roland_tmm 1:9dcccb399f0b 110 fq_ud = 0;
roland_tmm 1:9dcccb399f0b 111 wait_us(5);
roland_tmm 0:6069c0f2a245 112 fq_ud = 1;
roland_tmm 1:9dcccb399f0b 113 wait_us(5);
roland_tmm 0:6069c0f2a245 114 fq_ud = 0;
roland_tmm 0:6069c0f2a245 115 }
roland_tmm 0:6069c0f2a245 116
roland_tmm 0:6069c0f2a245 117
roland_tmm 0:6069c0f2a245 118 void AD9850::up() {
roland_tmm 0:6069c0f2a245 119 update();
roland_tmm 0:6069c0f2a245 120 }
roland_tmm 0:6069c0f2a245 121
roland_tmm 0:6069c0f2a245 122
roland_tmm 0:6069c0f2a245 123 void AD9850::CalibrateDDS(double TrimFreq)
roland_tmm 0:6069c0f2a245 124 {
roland_tmm 0:6069c0f2a245 125 calibFreq = TrimFreq;
roland_tmm 0:6069c0f2a245 126 }
roland_tmm 0:6069c0f2a245 127
roland_tmm 1:9dcccb399f0b 128 int AD9850::ReverseBits(int value)
roland_tmm 1:9dcccb399f0b 129 {
roland_tmm 1:9dcccb399f0b 130 // Unfortunately need to invert bit order of the desired frequency setting since MBED only allows for MSB first from SPI. We need LSB first for AD9850
roland_tmm 1:9dcccb399f0b 131 int mask=0;;
roland_tmm 1:9dcccb399f0b 132 int i=0;
roland_tmm 1:9dcccb399f0b 133 int target=0;
roland_tmm 1:9dcccb399f0b 134 int bitTarget=0x80000000; // Hard-wired for 32-bit inversion
roland_tmm 1:9dcccb399f0b 135
roland_tmm 1:9dcccb399f0b 136 for (i=0;i<32;i++) { // ditto
roland_tmm 1:9dcccb399f0b 137 mask=1<<i;
roland_tmm 1:9dcccb399f0b 138 bitTarget=1<<(31-i); // ditto
roland_tmm 1:9dcccb399f0b 139
roland_tmm 1:9dcccb399f0b 140 if(value & mask)
roland_tmm 1:9dcccb399f0b 141 target=target | bitTarget;
roland_tmm 1:9dcccb399f0b 142 }
roland_tmm 1:9dcccb399f0b 143 return target;
roland_tmm 1:9dcccb399f0b 144 }