1 | //includes
|
2 | //////////
|
3 | #include "avr/io.h"
|
4 | #include <util/delay.h>
|
5 |
|
6 |
|
7 | //defines
|
8 | /////////
|
9 | #define DDS_MCLK 24000000 /* DDS Clock */
|
10 | #define DDS_CONSTANT 0x10000000 /* 2^28 */
|
11 | #define DDS_DDR DDRD /* data direction reg*/
|
12 | #define DDS_PORT PORTD
|
13 | #define DDS_SDATA PIN0
|
14 | #define DDS_SCLCK PIN1
|
15 | #define DDS_FSYNC PIN2
|
16 |
|
17 |
|
18 | #define A PINA1 // Schalter A im Drehgeber
|
19 | #define B PINA0 // Schalter B im Drehgeber
|
20 | #define Geber PINA // Drehgeber Port
|
21 |
|
22 |
|
23 | //predeclarations
|
24 | void DDS_WriteWord(int16_t wValue);
|
25 | void ToggleDDSPIN(int nBit);
|
26 | void RotaryBlink(void);
|
27 | void DebounceKey(int nPort, int nPin);
|
28 | void SetFrequency(int32_t dwFreq);
|
29 |
|
30 |
|
31 | //calculate codeword:
|
32 | //CW = (Freq / DDS_MCLK) * DDS_CONSTANT
|
33 | //for 5 mhz with 25 MHz clock: 0x33333333
|
34 |
|
35 |
|
36 |
|
37 | int main(void)
|
38 | {
|
39 | //variables
|
40 | ///////////
|
41 | int32_t dwFreq = 1000000;
|
42 |
|
43 | int richtung = 0;
|
44 | char alter_status = 0;
|
45 | char step = 0;
|
46 | char neuer_status;
|
47 |
|
48 |
|
49 | //port init
|
50 | DDS_PORT = 0x0;
|
51 | DDS_DDR = 0xFF; //all output
|
52 |
|
53 |
|
54 | DDRA = 0x0; //all input
|
55 | PORTA = 0xFF; //pull up
|
56 |
|
57 | DDRC = 0xFF; //all output
|
58 | PORTC = 0x00; //no pull up
|
59 |
|
60 | //wait before we init
|
61 | //the ad9833
|
62 | _delay_ms(1000);
|
63 |
|
64 |
|
65 | SetFrequency(dwFreq);
|
66 |
|
67 |
|
68 | RotaryBlink();
|
69 | RotaryBlink();
|
70 |
|
71 |
|
72 |
|
73 | while(1)
|
74 | {
|
75 | neuer_status = Geber & (_BV(A) | _BV(B)); // Änderung einlesen
|
76 | if ((neuer_status ^ step)==(_BV(A) | _BV(B)))
|
77 | {
|
78 | if ((neuer_status ^ alter_status) ==_BV(A))
|
79 | {
|
80 | richtung +=1; // Es war nach rechts
|
81 | RotaryBlink();
|
82 |
|
83 | dwFreq += 1000;
|
84 | SetFrequency(dwFreq);
|
85 | }
|
86 | else
|
87 | {
|
88 | richtung -=1; // Es war nach links
|
89 | RotaryBlink();
|
90 |
|
91 | dwFreq -= 1000;
|
92 | SetFrequency(dwFreq);
|
93 | }
|
94 |
|
95 | step = neuer_status;
|
96 | }
|
97 |
|
98 | alter_status = neuer_status;
|
99 |
|
100 |
|
101 |
|
102 | /*
|
103 | if((PINA & 0x2) == 0x0)
|
104 | {
|
105 | RotaryBlink();
|
106 |
|
107 | dwFreq += 10000;
|
108 | SetFrequency(dwFreq);
|
109 | DebounceKey(PINA, 0x2);
|
110 | };
|
111 |
|
112 | if((PINA & 0x4) == 0x0)
|
113 | {
|
114 | RotaryBlink();
|
115 | RotaryBlink();
|
116 |
|
117 | dwFreq -= 10000;
|
118 | SetFrequency(dwFreq);
|
119 | DebounceKey(PINA, 0x4);
|
120 | };
|
121 | */
|
122 | }
|
123 |
|
124 | return 0;
|
125 | }
|
126 |
|
127 |
|
128 |
|
129 | void SetFrequency(int32_t dwFreq)
|
130 | {
|
131 | //variables
|
132 | ///////////
|
133 | float fVal = ((float)dwFreq / (float)DDS_MCLK);
|
134 | int32_t dwCodeWord = fVal * DDS_CONSTANT;
|
135 | int16_t wWord = 0x0;
|
136 |
|
137 | //send the control byte
|
138 | wWord = 0x2000; //0010 0000 0000 0000
|
139 | DDS_WriteWord(wWord);
|
140 |
|
141 | _delay_ms(1);
|
142 |
|
143 |
|
144 |
|
145 | //send lsb
|
146 | wWord = (dwCodeWord & 0x00003FFF); //lsb
|
147 | wWord |= 0x4000;
|
148 | DDS_WriteWord(wWord);
|
149 |
|
150 | _delay_ms(1);
|
151 |
|
152 |
|
153 |
|
154 | //send msb
|
155 | wWord = (dwCodeWord & 0x0FFFC000) >> 14; //msb
|
156 | wWord |= 0x4000; //set bit 15
|
157 | DDS_WriteWord(wWord);
|
158 | }
|
159 |
|
160 |
|
161 |
|
162 | /*
|
163 | AD9833 to 80C51/80L51 Interface
|
164 | Figure 12 shows the serial interface between the AD9833 and the
|
165 | 80C51/80L51 microcontroller. The microcontroller is operated
|
166 | in mode 0 so that TXD of the 80C51/80L51 drives SCLK of
|
167 | the AD9833, while RXD drives the serial data line SDATA. The
|
168 | FSYNC signal is again derived from a bit programmable pin on
|
169 | the port (P3.3 being used in the diagram). When data is to be
|
170 | transmitted to the AD9833, P3.3 is taken low. The 80C51/80L51
|
171 | transmits data in 8-bit bytes, thus only eight falling SCLK edges
|
172 | occur in each cycle. To load the remaining 8 bits to the AD9833,
|
173 | P3.3 is held low after the first 8 bits have been transmitted, and
|
174 | a second write operation is initiated to transmit the second byte of
|
175 | data. P3.3 is taken high following the completion of the second
|
176 | write operation. SCLK should idle high between the two write
|
177 | operations. The 80C51/80L51 outputs the serial data in a format
|
178 | that has the LSB first. The AD9833 accepts the MSB first
|
179 | (the 4 MSBs being the control information, the next 4 bits being
|
180 | the address, while the 8 LSBs contain the data when writing to a
|
181 | destination register). Therefore, the transmit routine of the
|
182 | 80C51/80L51 must take this into account and rearrange the bits
|
183 | so that the MSB is output first.
|
184 |
|
185 |
|
186 |
|
187 |
|
188 | 6 SDATA Serial Data Input. The 16-bit serial data-word is applied to this input.
|
189 | 7 SCLK Serial Clock Input. Data is clocked into the AD9833 on each falling SCLK edge.
|
190 | 8 FSYNC Active Low Control Input. This is the frame synchronization signal for the
|
191 | input data. When FSYNC is taken low, the
|
192 | new word is being loaded into the device.
|
193 |
|
194 |
|
195 | http://www.roboternetz.de/wissen/index.php/Portexpander_am_AVR#Ohne_SPI-Hardware
|
196 | */
|
197 | void DDS_WriteWord(int16_t wValue)
|
198 | {
|
199 | //variables
|
200 | ///////////
|
201 | int nBit = 0;
|
202 | int n = 0;
|
203 | uint16_t wVal = wValue;
|
204 |
|
205 | //init
|
206 | DDS_PORT = DDS_PORT & ~(1 << DDS_SDATA);
|
207 | DDS_PORT = DDS_PORT | (1 << DDS_SCLCK); //set
|
208 | DDS_PORT = DDS_PORT | (1 << DDS_FSYNC); //set
|
209 |
|
210 | _delay_ms(1);
|
211 |
|
212 |
|
213 |
|
214 | DDS_PORT &= ~(1 << DDS_FSYNC); //remove
|
215 |
|
216 | _delay_ms(1);
|
217 |
|
218 |
|
219 |
|
220 |
|
221 | for(n = 0; n < 16; ++n)
|
222 | {
|
223 | nBit = (wVal & 0x8000) >> 15;
|
224 | wVal = wVal << 1; //shift
|
225 |
|
226 | ToggleDDSPIN(nBit);
|
227 | };
|
228 |
|
229 |
|
230 | DDS_PORT = DDS_PORT | (1 << DDS_FSYNC); //set
|
231 |
|
232 | _delay_ms(1);
|
233 | }
|
234 |
|
235 |
|
236 |
|
237 |
|
238 | void ToggleDDSPIN(int nBit)
|
239 | {
|
240 | if(nBit == 1)
|
241 | {
|
242 | DDS_PORT = DDS_PORT | (1 << DDS_SDATA); //set
|
243 | }
|
244 |
|
245 | _delay_ms(1);
|
246 |
|
247 |
|
248 |
|
249 |
|
250 | DDS_PORT = DDS_PORT & ~(1 << DDS_SCLCK); //remove
|
251 |
|
252 | _delay_ms(1);
|
253 |
|
254 |
|
255 |
|
256 | DDS_PORT = DDS_PORT | (1 << DDS_SCLCK); //set
|
257 |
|
258 | _delay_ms(1);
|
259 |
|
260 |
|
261 |
|
262 | DDS_PORT = DDS_PORT & ~(1 << DDS_SDATA); //remove
|
263 | }
|
264 |
|
265 |
|
266 | void RotaryBlink(void)
|
267 | {
|
268 | PORTC = (1 << PIN0);
|
269 |
|
270 | _delay_ms(10);
|
271 |
|
272 | PORTC &= ~(1 << PIN0);
|
273 |
|
274 | _delay_ms(10);
|
275 | }
|
276 |
|
277 |
|
278 | void DebounceKey(int nPort, int nPin)
|
279 | {
|
280 | while((nPort & nPin) == 0)
|
281 | {
|
282 | //do nothing
|
283 | _delay_ms(1);
|
284 | }
|
285 | }
|