1 | #include <util/delay.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include <avr/io.h>
|
4 | #include <util/delay.h>
|
5 |
|
6 |
|
7 | //eigene defines, nicht verändern!
|
8 | #define DDR(x) (*(&x - 1))
|
9 | #define AUS 0
|
10 | #define SINUS 1
|
11 | #define RECHTECK 2
|
12 | #define RECHTECK2 3
|
13 | #define DREIECK 4
|
14 | #define B28 13
|
15 | #define HLB 12
|
16 | #define FSELECT 11
|
17 | #define PSELECT 10
|
18 | #define RESET 8
|
19 | #define SLEEP1 7
|
20 | #define SLEEP12 6
|
21 | #define OPBITEN 5
|
22 | #define DIV2 3
|
23 | #define MODE 1
|
24 | #define FREQ0 18
|
25 | #define FREQ1 28
|
26 | #define PHASE0 38
|
27 | #define PHASE1 48
|
28 | #define pi2 6.2832
|
29 |
|
30 | /*************************************Konfiguration***************************************/
|
31 | //MasterClock des AD9833
|
32 | #define MCLK 25000000
|
33 |
|
34 | //SPI - SS muss den gleichen Port haben wie der Hardware SPI
|
35 | #define SPIPORT PORTB
|
36 | #define MOSI 5
|
37 | #define SCK 7
|
38 | #define SS 4
|
39 | /*************************************Konfiguration***************************************/
|
40 |
|
41 | //enthält den momentanen Status des AD9833
|
42 | uint16_t stats = 0;
|
43 | uint16_t tosend = 0;
|
44 | double konst = 268435456; //2^28, (1<<28)
|
45 | float konst2 = 4096; //2^12, (1<<12);
|
46 |
|
47 | //schreibt ein Wort in den AD9833
|
48 | void DDS_write(uint16_t data){
|
49 | SPIPORT &= ~(1<<SS);
|
50 | SPDR = (uint8_t)(data>>8);
|
51 | while(!(SPSR & (1<<SPIF)))
|
52 | ;
|
53 | SPDR = (uint8_t)(data & 255);
|
54 | while(!(SPSR & (1<<SPIF)))
|
55 | ;
|
56 | SPIPORT |= (1<<SS);
|
57 | }
|
58 |
|
59 | //resettet den Zähler des AD9833 und schaltte ihn ab, DAC getrennt
|
60 | void DDS_off(void){
|
61 | //complete word write, Counter reset, MCLK Off, DAC disconnected, SINROM bypass
|
62 | stats = (1<<B28) | (1<<RESET) | (1<<SLEEP1) | (1<<OPBITEN) | (1<<MODE);
|
63 | DDS_write(stats);
|
64 | stats &= ~(1<<RESET);
|
65 | _delay_ms(1);
|
66 | DDS_write(stats);
|
67 | }
|
68 |
|
69 | //initilaisiert den Hardware SPI und den AD9833
|
70 | void DDS_init(void){
|
71 | //SPI Init
|
72 | DDR(SPIPORT) |= (1<<MOSI) | (1<<SCK) | (1<<SS);
|
73 | SPIPORT |= (1<<SS);
|
74 | //MSB zuerst, Master, SCK Idle High, CLK/16
|
75 | SPCR = (1<<SPE)| (1<<MSTR) | (1<<CPOL) | (1<<SPR0);
|
76 | //DDS Init
|
77 | DDS_off();
|
78 | }
|
79 |
|
80 | //schaltet die Signalform des AD9833 um
|
81 | //SINUS, DREIECK, RECHTECK, RECHTECK2, AUS
|
82 | void DDS_signal (uint8_t signal){
|
83 | switch (signal){
|
84 | case AUS:
|
85 | DDS_off();
|
86 | break;
|
87 | case SINUS:
|
88 | stats &= ~((1<<OPBITEN) | (1<<MODE) | (1<<SLEEP1));
|
89 | break;
|
90 | case RECHTECK2:
|
91 | stats &= ~((1<<MODE) | (1<<DIV2) | (1<<SLEEP1));
|
92 | stats |= (1<<OPBITEN);
|
93 | break;
|
94 | case RECHTECK:
|
95 | stats |= (1<<OPBITEN) | (1<<DIV2);
|
96 | stats &= ~((1<<MODE) | (1<<SLEEP1));
|
97 | break;
|
98 | case DREIECK:
|
99 | stats &= ~((1<<OPBITEN) | (1<<SLEEP1));
|
100 | stats |= (1<<MODE);
|
101 | break;
|
102 | default:
|
103 | stats |= (1<<OPBITEN) | (1<<MODE);
|
104 | }
|
105 | DDS_write(stats);
|
106 | }
|
107 |
|
108 | //Auswahl des AD9833 Registers, welches für die Frequenz/Phase zuständig ist
|
109 | //FREQ0, FREQ1, PHASE0, PHASE1
|
110 | void DDS_reg(uint8_t reg){
|
111 | switch (reg){
|
112 | case FREQ0:
|
113 | stats &= ~(1<<FSELECT);
|
114 | break;
|
115 | case FREQ1:
|
116 | stats |= (1<<FSELECT);
|
117 | break;
|
118 | case PHASE0:
|
119 | stats &= ~(1<<PSELECT);
|
120 | break;
|
121 | case PHASE1:
|
122 | stats |= (1<<PSELECT);
|
123 | break;
|
124 | default:
|
125 | stats &= ~((1<<FSELECT) | (1<<PSELECT));
|
126 | }
|
127 | DDS_write(stats);
|
128 | }
|
129 |
|
130 | //stellt den AD9833 auf die gewünschte Freqenz in Hz ein
|
131 | //der Wert wird in das angegebene Register geschrieben (FREQ0, FREQ1)
|
132 | void DDS_freq(uint32_t frequenz, uint8_t reg){
|
133 | double temp = ((double)frequenz/(double)MCLK);
|
134 | uint32_t regist = temp * konst;
|
135 | tosend = regist & 16383;
|
136 | if (reg == FREQ0){tosend |= (1<<14);}
|
137 | if (reg == FREQ1){tosend |= (1<<15);}
|
138 | DDS_write(tosend);
|
139 | tosend = (regist & ~16383)>>14;
|
140 | if (reg == FREQ0){tosend |= (1<<14);}
|
141 | if (reg == FREQ1){tosend |= (1<<15);}
|
142 | DDS_write(tosend);
|
143 | }
|
144 |
|
145 | //stellt den AD9833 auf die gewünschte Phase ein
|
146 | //der Wert wird in das angegebene Register geschrieben (PHASE0, PHASE1)
|
147 | void DDS_phase(uint16_t phase, uint8_t reg){
|
148 | uint16_t regist = (uint16_t) (phase*konst2)/pi2;
|
149 | tosend = (1<<15) | (1<<14);
|
150 | if (reg == PHASE1){tosend |= (1<<13);}
|
151 | DDS_write(tosend | regist);
|
152 | }
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 | int main()
|
159 | {
|
160 | DDRD |= (1 << 6);
|
161 | PORTD |= (1 << 6); //hier gehen die SPI-Pins auf low
|
162 | _delay_ms(200);
|
163 | PORTD &= ~(1 << 6); //und hier wieder auf high
|
164 |
|
165 | DDS_init();
|
166 |
|
167 | DDS_signal(SINUS);
|
168 |
|
169 | DDS_phase(0, PHASE0);
|
170 |
|
171 | DDS_freq(1000, FREQ0);
|
172 |
|
173 |
|
174 | PORTD |= (1 << 6);
|
175 | _delay_ms(200);
|
176 | PORTD &= ~(1 << 6);
|
177 |
|
178 | }
|