A sine wave generator using AD9833 and AD9850 using STM32F103RB
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
AD9850.cpp@0:6069c0f2a245, 2017-11-21 (annotated)
- Committer:
- roland_tmm
- Date:
- Tue Nov 21 11:24:25 2017 +0000
- Revision:
- 0:6069c0f2a245
- Child:
- 1:9dcccb399f0b
Version 1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
roland_tmm | 0:6069c0f2a245 | 1 | /****************************************************************************************************************** |
roland_tmm | 0:6069c0f2a245 | 2 | * STM32F103 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 | #define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)]) |
roland_tmm | 0:6069c0f2a245 | 34 | |
roland_tmm | 0:6069c0f2a245 | 35 | static const uint8_t reverse_lookup[] = { 0, 8, 4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 }; |
roland_tmm | 0:6069c0f2a245 | 36 | |
roland_tmm | 0:6069c0f2a245 | 37 | SPI SPI_dev2(DATA, PB_8, W_CLK); |
roland_tmm | 0:6069c0f2a245 | 38 | |
roland_tmm | 0:6069c0f2a245 | 39 | DigitalOut wclk(W_CLK); |
roland_tmm | 0:6069c0f2a245 | 40 | DigitalOut fq_ud(FQ_UD); |
roland_tmm | 0:6069c0f2a245 | 41 | DigitalOut dat(DATA); |
roland_tmm | 0:6069c0f2a245 | 42 | DigitalOut res(RESET); |
roland_tmm | 0:6069c0f2a245 | 43 | |
roland_tmm | 0:6069c0f2a245 | 44 | AD9850::AD9850() { |
roland_tmm | 0:6069c0f2a245 | 45 | |
roland_tmm | 0:6069c0f2a245 | 46 | } |
roland_tmm | 0:6069c0f2a245 | 47 | |
roland_tmm | 0:6069c0f2a245 | 48 | void AD9850::Begin() { |
roland_tmm | 0:6069c0f2a245 | 49 | SPI_dev2.format(8,0); |
roland_tmm | 0:6069c0f2a245 | 50 | deltaphase = 0; |
roland_tmm | 0:6069c0f2a245 | 51 | phase = 0; |
roland_tmm | 0:6069c0f2a245 | 52 | calibFreq = 125000000; |
roland_tmm | 0:6069c0f2a245 | 53 | begin_priv(); |
roland_tmm | 0:6069c0f2a245 | 54 | } |
roland_tmm | 0:6069c0f2a245 | 55 | |
roland_tmm | 0:6069c0f2a245 | 56 | void AD9850::begin_priv() { |
roland_tmm | 0:6069c0f2a245 | 57 | |
roland_tmm | 0:6069c0f2a245 | 58 | res = 1; |
roland_tmm | 0:6069c0f2a245 | 59 | wait(0.001); |
roland_tmm | 0:6069c0f2a245 | 60 | res = 0; |
roland_tmm | 0:6069c0f2a245 | 61 | |
roland_tmm | 0:6069c0f2a245 | 62 | wclk = 1; |
roland_tmm | 0:6069c0f2a245 | 63 | wait(0.001); |
roland_tmm | 0:6069c0f2a245 | 64 | wclk = 0; |
roland_tmm | 0:6069c0f2a245 | 65 | |
roland_tmm | 0:6069c0f2a245 | 66 | fq_ud = 1; |
roland_tmm | 0:6069c0f2a245 | 67 | wait(0.001); |
roland_tmm | 0:6069c0f2a245 | 68 | fq_ud = 0; |
roland_tmm | 0:6069c0f2a245 | 69 | |
roland_tmm | 0:6069c0f2a245 | 70 | } |
roland_tmm | 0:6069c0f2a245 | 71 | |
roland_tmm | 0:6069c0f2a245 | 72 | void AD9850::update() { |
roland_tmm | 0:6069c0f2a245 | 73 | uint32_t d,p; |
roland_tmm | 0:6069c0f2a245 | 74 | for (int i=0; i<4; i++, deltaphase>>=8) { |
roland_tmm | 0:6069c0f2a245 | 75 | d = REVERSE_BITS(deltaphase); |
roland_tmm | 0:6069c0f2a245 | 76 | SPI_dev2.write(d & 0xFF); |
roland_tmm | 0:6069c0f2a245 | 77 | // shiftOut(DATA, W_CLK, LSBFIRST, deltaphase & 0xFF); |
roland_tmm | 0:6069c0f2a245 | 78 | } |
roland_tmm | 0:6069c0f2a245 | 79 | p = REVERSE_BITS(phase); |
roland_tmm | 0:6069c0f2a245 | 80 | SPI_dev2.write(p & 0xFF); |
roland_tmm | 0:6069c0f2a245 | 81 | //shiftOut(DATA, W_CLK, LSBFIRST, phase & 0xFF); |
roland_tmm | 0:6069c0f2a245 | 82 | fq_ud = 1; |
roland_tmm | 0:6069c0f2a245 | 83 | wait(0.001); |
roland_tmm | 0:6069c0f2a245 | 84 | fq_ud = 0; |
roland_tmm | 0:6069c0f2a245 | 85 | } |
roland_tmm | 0:6069c0f2a245 | 86 | |
roland_tmm | 0:6069c0f2a245 | 87 | |
roland_tmm | 0:6069c0f2a245 | 88 | void AD9850::SetDDSFrequency(double f, uint8_t p) { |
roland_tmm | 0:6069c0f2a245 | 89 | deltaphase = f * 4294967296.0 / calibFreq; |
roland_tmm | 0:6069c0f2a245 | 90 | phase = p << 3; |
roland_tmm | 0:6069c0f2a245 | 91 | update(); |
roland_tmm | 0:6069c0f2a245 | 92 | } |
roland_tmm | 0:6069c0f2a245 | 93 | |
roland_tmm | 0:6069c0f2a245 | 94 | |
roland_tmm | 0:6069c0f2a245 | 95 | void AD9850::down() { |
roland_tmm | 0:6069c0f2a245 | 96 | fq_ud = 1; |
roland_tmm | 0:6069c0f2a245 | 97 | wait(0.001); |
roland_tmm | 0:6069c0f2a245 | 98 | fq_ud = 0; |
roland_tmm | 0:6069c0f2a245 | 99 | SPI_dev2.write(REVERSE_BITS(0x04)); |
roland_tmm | 0:6069c0f2a245 | 100 | //shiftOut(DATA, W_CLK, LSBFIRST, 0x04); |
roland_tmm | 0:6069c0f2a245 | 101 | fq_ud = 1; |
roland_tmm | 0:6069c0f2a245 | 102 | wait(0.001); |
roland_tmm | 0:6069c0f2a245 | 103 | fq_ud = 0; |
roland_tmm | 0:6069c0f2a245 | 104 | } |
roland_tmm | 0:6069c0f2a245 | 105 | |
roland_tmm | 0:6069c0f2a245 | 106 | |
roland_tmm | 0:6069c0f2a245 | 107 | void AD9850::up() { |
roland_tmm | 0:6069c0f2a245 | 108 | update(); |
roland_tmm | 0:6069c0f2a245 | 109 | } |
roland_tmm | 0:6069c0f2a245 | 110 | |
roland_tmm | 0:6069c0f2a245 | 111 | |
roland_tmm | 0:6069c0f2a245 | 112 | void AD9850::CalibrateDDS(double TrimFreq) |
roland_tmm | 0:6069c0f2a245 | 113 | { |
roland_tmm | 0:6069c0f2a245 | 114 | calibFreq = TrimFreq; |
roland_tmm | 0:6069c0f2a245 | 115 | } |
roland_tmm | 0:6069c0f2a245 | 116 | |
roland_tmm | 0:6069c0f2a245 | 117 | /* |
roland_tmm | 0:6069c0f2a245 | 118 | void AD9850::pulse(int pin) { |
roland_tmm | 0:6069c0f2a245 | 119 | digitalWrite(pin, HIGH); |
roland_tmm | 0:6069c0f2a245 | 120 | digitalWrite(pin, LOW); |
roland_tmm | 0:6069c0f2a245 | 121 | }*/ |