1 | /*
|
2 | * ADC_Test.asm
|
3 | *
|
4 | * Created: 03.08.2013 18:25:48
|
5 | * Author: Christian Felix
|
6 | *
|
7 | * testet den ADC des ATxmega128A4U
|
8 | * konvertiert permanent die Spannung am Eingang Pin PA1
|
9 | * und sendet die Ergebnisse als Datenpakete von jeweils 1792 words
|
10 | * über USARTE0 an den PC
|
11 | *
|
12 | */
|
13 |
|
14 | .def zero = r11 ; immer 0, für 16-bit Addition
|
15 | .def count = r12
|
16 | .def count2 = r13
|
17 | .def count3 = r14
|
18 | .def count4 = r15
|
19 | .def temp = r16
|
20 | .def temp2 = r17
|
21 | .def temp3 = r18
|
22 | .def temp4 = r19
|
23 | .def temp5 = r20
|
24 |
|
25 | .equ DISPLAY_SIZE = 100
|
26 |
|
27 |
|
28 | ; setze Interrupt Sprung-Adressen:
|
29 | ; --------------------------------
|
30 |
|
31 | .org 0x000 rjmp main
|
32 | .org USARTE0_TXC_vect rjmp USARTE0_TXC ; TXC (data transmit complete) Interrupt-Adresse USARTE0
|
33 |
|
34 |
|
35 | ; Start Hauptprogramm:
|
36 | ; --------------------
|
37 |
|
38 | main: ; Stack initialisieren
|
39 | ldi temp, HIGH(RAMEND)
|
40 | out CPU_SPH, temp
|
41 | ldi temp, LOW(RAMEND)
|
42 | out CPU_SPL, temp
|
43 |
|
44 | ; initialisiere zero register:
|
45 | clr zero
|
46 |
|
47 | ; schalte System-Clock auf 32MHz um (zusätzlich 16,7mA, mit 2MHz sind's 3,22mA)
|
48 | rcall CLOCK_32MHZ
|
49 |
|
50 | ; initialisiere USARTE:
|
51 | rcall USART_INI
|
52 |
|
53 | ; Datenrichtung Ports, Remap, Pin Konfiguration, Ladungspumpe ein:
|
54 | rcall DEFINE_PORTS
|
55 |
|
56 | ; Ringspeicher / Pointer für PC-Display initialisieren:
|
57 | rcall DSP_INI
|
58 |
|
59 | ; ADCA kalibrieren:
|
60 | rcall ADCA_CALIBRATE
|
61 |
|
62 | ; setze Event-System:
|
63 | //rcall SET_EVENTSYSTEM
|
64 |
|
65 |
|
66 | ; ===================================================================
|
67 | ;
|
68 | ; ADC konfigurieren
|
69 | ;
|
70 | ; -------------------------------------------------------------------
|
71 |
|
72 | ; Conversion mode
|
73 | ldi temp, 0b10110000 ; IMPMODE = 1 = low impedance source; CURRLIMIT = 01 = LOW; CONVMODE = 1 = signed mode
|
74 | ; FREERUN = 0; RESOLUTION = 00 = 12bit right adjusted
|
75 | sts ADCA_CTRLB, temp
|
76 |
|
77 | ; external voltage reference pin A0, AREF0 (1,6V):
|
78 | ldi temp, 0b00100000 ; REFSEL[2:0] = 010 = AREFA
|
79 | sts ADCA_REFCTRL, temp
|
80 |
|
81 | ; ADC clock setzen: 0.5MHz
|
82 | // ldi temp, 0b00000011 ; prescaler 32
|
83 | ldi temp, 0b00000100 ; prescaler 64
|
84 | // ldi temp, 0b00000101 ; prescaler 128
|
85 | // ldi temp, 0b00000111 ; prescaler 512
|
86 | sts ADCA_PRESCALER, temp
|
87 |
|
88 | ; Kanäle setzen:
|
89 | ; --------------
|
90 |
|
91 | ; Channel 0: für alle Input-Pins single ended (ADCA in signed mode):
|
92 | ldi temp, 0b00000001 ; START = 0
|
93 | ; INPUTMODE[1:0] = 01 = Single ended
|
94 | sts ADCA_CH0_CTRL, temp
|
95 |
|
96 | ; Poti: Channel 0 ADC pin 1: PA1, single ended, signed mode
|
97 | ldi temp, 0b00001000 ; MUXPOS[3:0] = 0001 = PIN1 = ADC1 pin = PA1
|
98 | ; MUXNEG[2:0] = 000
|
99 | sts ADCA_CH0_MUXCTRL, temp
|
100 |
|
101 | ; ADCA enablen und flushen:
|
102 | ldi temp, 0b00000011 ; no DMA, no START, FLUSH, ENABLE
|
103 | sts ADCA_CTRLA, temp
|
104 |
|
105 |
|
106 | ; ===================================================================
|
107 | ;
|
108 | ; Interrupt level für USART definieren
|
109 | ;
|
110 | ; -------------------------------------------------------------------
|
111 |
|
112 | ; enable low level interrupt für Datenübertragung zum PC:
|
113 | ldi temp, 0b00000001 ; RREN = 0: no round robin for low level interrupts
|
114 | ; IVSEL = 0: interrupt vectots are placed at the start of the application section
|
115 | ; HILVLEN = 0: high level interrupt disabled
|
116 | ; MEDLVLEN = 0: medium level interrupt disabled
|
117 | ; LOLVLEN = 1: enable low level interrupt
|
118 | sts PMIC_CTRL, temp
|
119 |
|
120 | ; global interrupt einschalten:
|
121 | sei
|
122 |
|
123 |
|
124 | ; ===================================================================
|
125 | ;
|
126 | ; ADC-Test-Start
|
127 | ;
|
128 | ; -------------------------------------------------------------------
|
129 |
|
130 | ; warten bis Kondensatoren aufgeladen sind:
|
131 | ldi temp3, 200
|
132 | rcall wait
|
133 |
|
134 | ADC_repeat:
|
135 | rcall DSP_CLR_ALL
|
136 |
|
137 | clr count
|
138 |
|
139 | clr XL
|
140 | clr XH
|
141 |
|
142 | ldi YH, HIGH(Poti_Samples)
|
143 | ldi YL, LOW(Poti_Samples)
|
144 |
|
145 |
|
146 | ADC_loop_0:
|
147 | ; warten. Hier Zahl erhöhen, falls PC zu langsam (kein Handshake mit PC).
|
148 | ldi temp3, 22
|
149 | rcall shortwait
|
150 |
|
151 | ; starte Channel 0:
|
152 | ldi temp, 0b00000101 ; no DMA, START CH_0, no FLUSH, ENABLE
|
153 | sts ADCA_CTRLA, temp
|
154 |
|
155 | ADC_wait_0:
|
156 | ; prüfe, ob Konversion für Channel 0 fertig:
|
157 | lds temp, ADCA_CH0_INTFLAGS
|
158 | tst temp
|
159 | breq ADC_wait_0
|
160 |
|
161 | /*
|
162 | ; lösche nun Flag (nicht nötig, wenn ADC nach Warteschleifen von Hand gestartet wird):
|
163 | ldi temp, 1
|
164 | sts ADCA_CH0_INTFLAGS, temp
|
165 | */
|
166 |
|
167 | ; 12bit Wert direkt von channel 0 lesen:
|
168 | lds temp, ADCA_CH0_RES ; Lo-Byte
|
169 | lds temp2, ADCA_CH0_RES+1 ; Hi-Byte
|
170 |
|
171 | ; Werte speichern:
|
172 | st Y+, temp
|
173 | st Y+, temp2
|
174 |
|
175 | adiw X, 1
|
176 | cpi XH, 7 ; 7*256 = 1792 Words
|
177 | brne ADC_loop_0
|
178 |
|
179 | ; Werte senden:
|
180 | ldi YH, HIGH(Poti_Samples)
|
181 | ldi YL, LOW(Poti_Samples)
|
182 |
|
183 | ADC_send:
|
184 | ld temp, Y+
|
185 | ld temp2, Y+
|
186 |
|
187 | rcall DSP_WRD_0
|
188 |
|
189 | sbiw X, 1
|
190 | cpi XH, 0
|
191 | brne ADC_send
|
192 | tst XL
|
193 | brne ADC_send
|
194 |
|
195 | rjmp ADC_repeat
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | ; ####################################################################################
|
201 | ; ########################### ################################
|
202 | ; ########################### Interrupt Handler ################################
|
203 | ; ########################### ################################
|
204 | ; ####################################################################################
|
205 |
|
206 | ; ====================================================================================
|
207 | ;
|
208 | ; USARTE0_TXC: Data transmit complete, nach erstem Byte alle weiteren versenden
|
209 | ;
|
210 | ; Nach Sendung des letzten Bytes wird Interrupt gestoppt.
|
211 | ;
|
212 | ; Kein Input, keine benutzten Register
|
213 | ;
|
214 | ; ------------------------------------------------------------------------------------
|
215 |
|
216 | USARTE0_TXC:
|
217 |
|
218 | push temp
|
219 | in temp, CPU_SREG
|
220 | push temp
|
221 | push ZL
|
222 | push ZH
|
223 |
|
224 | ; sende Byte:
|
225 | ldi ZL, LOW(Display_Pointer) ; Z: absolute Adresse für relativen Pointer auf zu sendendes Byte
|
226 | ldi ZH, HIGH(Display_Pointer)
|
227 | ld ZL, Z ; Z ist jetzt absoluter Pointer auf zu sendendes Byte
|
228 | ld temp, Z+ ; lade das Byte und setze Z auf nächstes zu sendendes Byte ...
|
229 | sts USARTE0_DATA, temp ; ... und senden
|
230 | cpi ZL, DISPLAY_SIZE ; hat relativer Pointer Ende des Ringspeichers erreicht?
|
231 | brlo USARTE0_TXC_pointer_beneath_limit
|
232 | clr ZL
|
233 |
|
234 | USARTE0_TXC_pointer_beneath_limit:
|
235 | ; speichere neuen Wert des relativen Pointers:
|
236 | mov temp, ZL
|
237 | ldi ZL, LOW(Display_Pointer) ; Z: absolute Adresse für relativen Pointer auf zu sendendes Byte
|
238 | st Z+, temp ; speichere neuen relativen Pointer und lade zugleich absolute Adresse Z für relativen Ende-Pointer
|
239 |
|
240 | ; vergleiche neuen Pointer mit Ende-Pointer: wenn gleich, Übertragung stoppen
|
241 | ld ZL, Z ; temp ist jetzt rel. Ende-Pointer
|
242 | cp temp, ZL ; rel. Ende-Pointer = rel. Pointer?
|
243 | brne USARTE0_TXC_end
|
244 |
|
245 | ; stoppe Interrupt, da gerade letztes Byte gesendet wird:
|
246 | sts USARTE0_CTRLA, zero ; disable interrupt
|
247 |
|
248 | USARTE0_TXC_end:
|
249 | pop ZH
|
250 | pop ZL
|
251 | pop temp
|
252 | out CPU_SREG, temp
|
253 | pop temp
|
254 |
|
255 | reti
|
256 |
|
257 |
|
258 | ; ####################################################################################
|
259 | ; ########################### ###################################
|
260 | ; ########################### Unterprogramme ###################################
|
261 | ; ########################### ###################################
|
262 | ; ####################################################################################
|
263 |
|
264 | ; lade Display-Programme:
|
265 | .include "../DisplayLib.inc"
|
266 |
|
267 |
|
268 | ; ====================================================================================
|
269 | ;
|
270 | ; DEFINE_PORTS: legt Datenrichtungen aller Ports fest, konfiguriert alle Pins, remap
|
271 | ;
|
272 | ; ------------------------------------------------------------------------------------
|
273 |
|
274 | DEFINE_PORTS:
|
275 |
|
276 | ; Virtuelle Ports definieren:
|
277 | ; ---------------------------
|
278 |
|
279 | ; Port C als virtuellen Port 0
|
280 | ; Port D als virtuellen Port 1
|
281 | ; Port E als virtuellen Port 2
|
282 | ; Port A als virtuellen Port 3
|
283 |
|
284 | ; definiere PORTC als virtuellen Port 0 und PORTD als virtuellen Port 1:
|
285 | ldi temp, 0b00110010 ; code für PORTC->virtuell 0 und PORTD->virtuell 1
|
286 | sts PORTCFG_VPCTRLA, temp ; Register für virtuelle Ports 0 und 1
|
287 | ; definiere PORTE als virtuellen Port 2 und PORTA als virtuellen Port 3:
|
288 | ldi temp, 0b00000100 ; code für PORTE->virtuell 2 und PORTA->virtuell 3
|
289 | sts PORTCFG_VPCTRLB, temp ; Register für virtuelle Ports 2 und 3
|
290 |
|
291 |
|
292 | ; Setze Port Pins auf Eingang / Ausgang je nach Bestimmung:
|
293 | ; ---------------------------------------------------------
|
294 |
|
295 | ; PA7: Eingang: leer (unused pin)
|
296 | ; PA6: Analog-Eingang: MUXNEG, verdrahtet mit AREF = 1,6V (=PA0)
|
297 | ; PA5: Analog-Eingang: MUXPOS, Ausgang Tiefpass Mikrofon-OpAmp MAX4488
|
298 | ; PA4: Analog-Eingang: PTC
|
299 | ; PA3: Analog-Eingang: LDR
|
300 | ; PA2: Analog-Eingang: Farbtemperatur-Poti
|
301 | ; PA1: Analog-Eingang: Helligkeits-Poti
|
302 | ; PA0: Analog-Eingang: AREF = 1,6V, verdrahtet mit MUXNEG (=PA6)
|
303 |
|
304 | ldi temp, 0b00000000
|
305 | sts VPORT3_DIR, temp ; Datenrichtungen für Port A festlegen
|
306 |
|
307 | ; PB3: Eingang: leer (unused pin)
|
308 | ; PB2: Eingang: leer (unused pin)
|
309 | ; PB1: Eingang: leer (unused pin)
|
310 | ; PB0: Ausgang: An/Aus Stromversorgung PTC
|
311 |
|
312 |
|
313 | ldi temp, 0b00000001
|
314 | sts PORTB_DIR, temp ; Datenrichtungen für Port B festlegen
|
315 |
|
316 | ; PC7: Ausgang: CLK_PER für Ladungspumpe
|
317 | ; PC6: Eingang: leer (unused pin)
|
318 | ; PC5: Ausgang: An/Aus Touch (Spannungsversorgung AT42QT1010 über 3,3V-Referenz)
|
319 | ; PC4: Eingang: Ergebnis Touch, Ausgang vom ATV42QT1010
|
320 | ; PC3: Ausgang: Timer TCC0 verdrahtet mit PC2 (Eingang), Mikrophon-Trigger 1:3
|
321 | ; PC2: Eingang: verdrahtet mit PC3, Mikrophon-Trigger 1:3
|
322 | ; PC1: Ausgang: Mikrofon-Verstärkerkreis An/Aus, enable OpAmp und 3,3V-LDO
|
323 | ; PC0: Eingang: leer (unused pin)
|
324 |
|
325 | ldi temp, 0b10101010
|
326 | out VPORT0_DIR, temp ; Datenrichtungen für Port C festlegen
|
327 |
|
328 | ; PD7: Ausgang: Blau RGB-LED, Remap TCD0 / OC0D
|
329 | ; PD6: Eingang: leer (unused pin)
|
330 | ; PD5: Ausgang: PWM Licht Kanal B, TCD1 / OC1B
|
331 | ; PD4: Ausgang: PWM Licht Kanal A, TCD1 / OC1A
|
332 | ; PD3: Eingang: leer (unused pin)
|
333 | ; PD2: Ausgang: enable OpAmps 1 und 2: Kanäle A und B
|
334 | ; PD1: Eingang: leer (unused pin)
|
335 | ; PD0: Ausgang: Umschaltung PWM / Analog, vier FET-Gates
|
336 |
|
337 | ldi temp, 0b10110101
|
338 | out VPORT1_DIR, temp ; Datenrichtungen für Port D festlegen
|
339 |
|
340 | ; PE3: Ausgang: USARTE0, TXD0
|
341 | ; PE2: Ausgang: USARTE0, RXD0
|
342 | ; PE1: Ausgang: Grün RGB-LED
|
343 | ; PE0: Ausgang: Rot RGB-LED
|
344 |
|
345 | ldi temp, 0b00001111
|
346 | sts VPORT2_DIR, temp ; Datenrichtungen für Port E festlegen
|
347 |
|
348 | ; PR1: Eingang: leer (unused pin)
|
349 | ; PR0: Eingang: leer (unused pin)
|
350 |
|
351 | ldi temp, 0b00000000
|
352 | sts PORTR_DIR, temp ; Datenrichtungen für Port R festlegen
|
353 |
|
354 |
|
355 | ; Lege die Eingänge nicht benutzter Pins auf Low (Port A, B, C, D, R):
|
356 | ; --------------------------------------------------------------------
|
357 |
|
358 | ldi temp2, 0b00010000 ; code für Totem-pole Pull-down (Pin level low)
|
359 |
|
360 | ; Port A:
|
361 | sts PORTA_PIN7CTRL, temp2 ; Totem-pole Pull-down
|
362 |
|
363 | ; Port B:
|
364 | ldi temp, 0b00001110 ; folgende PINnCTRL gilt für pins 3, 2, 1 (PB3, PB2, PB1)
|
365 | sts PORTCFG_MPCMASK, temp
|
366 | sts PORTB_PIN1CTRL, temp2 ; Totem-pole Pull-down
|
367 |
|
368 | ; Port C:
|
369 | ldi temp, 0b01000001 ; folgende PINnCTRL gilt für pins 6 und 0 (PC6 und PC0)
|
370 | sts PORTCFG_MPCMASK, temp
|
371 | sts PORTC_PIN0CTRL, temp2 ; Totem-pole Pull-down
|
372 |
|
373 | ; Port D:
|
374 | ldi temp, 0b01001010 ; folgende PINnCTRL gilt für pin 6, 3, 1 (PD6, PD3, PD1)
|
375 | sts PORTCFG_MPCMASK, temp
|
376 | sts PORTD_PIN1CTRL, temp2 ; Totem-pole Pull-down
|
377 |
|
378 | ; Port R:
|
379 | ldi temp, 0b00000011 ; folgende PINnCTRL gilt für pin 1 und 0 (PR1 und PR0)
|
380 | sts PORTCFG_MPCMASK, temp
|
381 | sts PORTR_PIN0CTRL, temp2 ; Totem-pole Pull-down
|
382 |
|
383 |
|
384 | ; Port A: schalte digitalen Input-Buffer für Analog-Eingänge aus:
|
385 | ; ---------------------------------------------------------------
|
386 |
|
387 | ldi temp2, 0b00000111 ; code für Digital input buffer disabled
|
388 | ldi temp, 0b01111111 ; folgende PINnCTRL gilt für pins 6...0 (PA6...PA0)
|
389 | sts PORTCFG_MPCMASK, temp
|
390 | sts PORTA_PIN0CTRL, temp2 ; Digital input buffer disabled
|
391 |
|
392 |
|
393 | ; Schalte Ladungspumpe für negative Spannung ein:
|
394 | ; -----------------------------------------------
|
395 |
|
396 | ldi temp, 0b10000000 ; slew rate limitation enable on PC7
|
397 | sts PORTC_PIN7CTRL, temp
|
398 | ldi temp, PORTCFG_CLKOUT_PC7_gc ; CLKper, also 32MHz (manual S.154), an PC7
|
399 | sts PORTCFG_CLKEVOUT, temp
|
400 |
|
401 |
|
402 | ; Remap pin PD3/PD7, PWM Timer/Counter Output Compare D für Blau RGB:
|
403 | ; -------------------------------------------------------------------
|
404 |
|
405 | ldi temp, 0b00001000 ; bit 3 - TC0D from PD3 to PD7 (manual p.150)
|
406 | sts PORTD_REMAP, temp
|
407 |
|
408 | ret
|
409 |
|
410 |
|
411 | ; ====================================================================================
|
412 | ;
|
413 | ; SET_EVENTSYSTEM
|
414 | ;
|
415 | ; setzt die event channels, um ADC-Kanäle zu triggern
|
416 | ;
|
417 | ; kein Input
|
418 | ;
|
419 | ; temp wird zerstört
|
420 | ;
|
421 | ; ------------------------------------------------------------------------------------
|
422 |
|
423 | SET_EVENTSYSTEM:
|
424 |
|
425 | ; Event channel 0 wird über die Clk_per getriggert, um ADCA-channel 0 zu
|
426 | ; triggern, an dem die Potis, PTC und LDR hängen:
|
427 | ; events sollen mit einer Taktrate von 62500 Hz getriggert werden, das
|
428 | ; ist ausreichend, um mit 1024 Hz für alle vier Pins, die an ADCA-Channel 0
|
429 | ; hängen, je 16 neue Konversionen zur Verfügung zu stellen, aus denen dann
|
430 | ; per CPU der Mittelwert gebildet werden kann.
|
431 | ldi temp, 0b10001001 ; PRESCALER M (1000) mit M = 9 (1001) = 32MHz/2e9 = 62500Hz
|
432 | ; wenn CPU mit 2MHz getaktet wird, dann diesen Wert verwenden:
|
433 | // ldi temp, 0b10000101 ; PRESCALER M (1000) mit M = 5 (0101) = 2MHz/2e5 = 62500Hz
|
434 | sts EVSYS_CH0MUX, temp
|
435 |
|
436 | ; Event channel 1 wird aktiv beim Flankenwechsel Pin PC2 (rising/falling edge on Pin PC2)
|
437 | ldi temp, 0b01100010 ; group configuration PORTC_PIN2 für CH1MUX
|
438 | sts EVSYS_CH1MUX, temp ; event channel 1
|
439 |
|
440 | ret
|
441 |
|
442 |
|
443 | ; ====================================================================================
|
444 | ;
|
445 | ; CLOCK_32MHZ
|
446 | ;
|
447 | ; change of internal clock from 2MHz to 32MHz
|
448 | ; Stromaufnahme der MPU steigt dabei um 22mA.
|
449 | ; Der interne 32MHz Oszillator läuft z.B. 5% zu schnell und muss
|
450 | ; kalibriert werden!
|
451 | ;
|
452 | ; ------------------------------------------------------------------------------------
|
453 |
|
454 | CLOCK_32MHZ:
|
455 |
|
456 | ldi temp, (1<<OSC_RC32KEN_bp | 1<<OSC_RC32MEN_bp | 1<<OSC_RC2MEN_bp) ; enable 32kHz and 32MHz clock and keep 2MHz clock running
|
457 | sts OSC_CTRL, temp
|
458 | ; warte bis 32MHz clock stabil läuft
|
459 | CLOCK_32MHZ_clock_wait:
|
460 | lds temp, OSC_STATUS
|
461 | andi temp, (1<<OSC_RC32KRDY_bp | 1<<OSC_RC32MRDY_bp) ; 32kHz and 32MHz clock ready bits ausmaskieren
|
462 | cpi temp, (1<<OSC_RC32KRDY_bp | 1<<OSC_RC32MRDY_bp) ; wenn bits gesetzt, dann laufen die Oszillatoren stabil
|
463 | brne CLOCK_32MHZ_clock_wait ; Schleife wird in der Regel nur zweimal durchlaufen
|
464 | ; 32MHz clock läuft jetzt stabil, ändere interne System clock über protected write sequence
|
465 | ldi temp, 0xD8 ; code für Zugriff auf Protected IO register
|
466 | sts CPU_CCP, temp ; ins CPU Configuration Change Protection schreiben, ab jetzt nur 4 clock cycles write möglich
|
467 | ldi temp, 0b00000001 ; code für Auswahl interne 32MHz clock
|
468 | sts CLK_CTRL, temp ; fertig - nach 3 clock cycles
|
469 | ; disable nun interne 2MHz clock:
|
470 | ldi temp, (1<<OSC_RC32KEN_bp | 1<<OSC_RC32MEN_bp | 0<<OSC_RC2MEN_bp) ; keep 32kHz and 32MHz clock running and stop 2MHz clock
|
471 | sts OSC_CTRL, temp
|
472 |
|
473 | ; calibrate the 32MHz internal Oszillator frequency:
|
474 | ldi temp, 0
|
475 | sts OSC_DFLLCTRL, temp ; calibration source for the 32MHz DFLL is the 32.768kHz internal oscillator
|
476 | ldi temp, 1<<DFLL_ENABLE_bp ; this bit enables the DFLL and auto-calibration of the internal oscillator
|
477 | sts DFLLRC32M_CTRL, temp ; the reference clock must be enabled and stable before the DFLL is enabled
|
478 |
|
479 | ret
|
480 |
|
481 | ; ====================================================================================
|
482 | ;
|
483 | ; ADCA_CALIBRATE
|
484 | ;
|
485 | ; ADCA kalibrieren.
|
486 | ; Achtung, hier keinen Code einfügen, kein Interrupt.
|
487 | ; Command Register des NVM-Controllers wird verändert.
|
488 | ;
|
489 | ; kein Input
|
490 | ;
|
491 | ; zerstört temp, temp2, temp3, Z-pointer
|
492 | ;
|
493 | ; ------------------------------------------------------------------------------------
|
494 |
|
495 | ADCA_CALIBRATE:
|
496 |
|
497 | ; Lo-Byte der ADCA-Kalibrierung zuerst lesen und in temp speichern
|
498 | ; Load the Z-pointer with the byte address to read (-> manuel p. 431)
|
499 | ldi ZL, PROD_SIGNATURES_START + NVM_PROD_SIGNATURES_ADCACAL0_offset
|
500 | clr ZH
|
501 | ; Load the NVM CMD register with the read user signature row / calibration row command
|
502 | ldi temp, NVM_CMD_READ_CALIB_ROW_gc
|
503 | sts NVM_CMD, temp
|
504 | ; Execute the LPM instruction
|
505 | lpm temp, Z ; in temp liegt jetzt das Lo-Byte der Kalibrierung
|
506 |
|
507 | ; nun das Hi-Byte der ADCA-Kalibrierung lesen und in temp2 speichern
|
508 | ; Load the Z-pointer with the byte address to read
|
509 | ldi ZL, PROD_SIGNATURES_START + NVM_PROD_SIGNATURES_ADCACAL1_offset
|
510 | ; Execute the LPM instruction:
|
511 | lpm temp2, Z ; in temp2 liegt jetzt das Hi-Byte der Kalibrierung
|
512 |
|
513 | ; NVM CMD register wieder in den Normalzustand versetzen:
|
514 | ldi temp3, NVM_CMD_NO_OPERATION_gc
|
515 | sts NVM_CMD, temp3
|
516 |
|
517 | ; ADC-Kalibrierungsregister beschreiben:
|
518 | sts ADCA_CAL, temp ; Lo-Byte
|
519 | sts ADCA_CAL+1, temp2 ; Hi-Byte
|
520 |
|
521 | ret
|
522 |
|
523 |
|
524 | ; ==================================================================================
|
525 | ;
|
526 | ; USART_INI
|
527 | ;
|
528 | ; Kommunikationseinstellungen RS485-Schnittstelle für USARTE0 @ f_CPU = 32 MHz
|
529 | ;
|
530 | ; ----------------------------------------------------------------------------------
|
531 |
|
532 | USART_INI:
|
533 |
|
534 | ; schalte zunächst Receiver und Transmitter von USARTE0 aus, dadurch wird Receiver Buffer geflushed:
|
535 | ldi temp, 0
|
536 | sts USARTE0_CTRLB, temp
|
537 |
|
538 |
|
539 | ; initialize USARTE0 using initialization sequence as described in the manual p. 296:
|
540 | ldi temp, 0b00000001 ; setze Baudrate auf 1MHz
|
541 | sts USARTE0_BAUDCTRLA, temp ; BSEL[7:0] = 1
|
542 | ldi temp, 0b00000000
|
543 | sts USARTE0_BAUDCTRLB, temp ; BSCALE[3:0] = 0 BSEL[11:8] = 0 und => Baudrate = f_CPU/(16*(1+1)) = 1MHz
|
544 |
|
545 | ldi temp, 0b00100011 ; CMODE[1:0] = 00 = asynchronous mode
|
546 | ; PMODE[1:0] = 10 = even parity
|
547 | ; SBMODE = 0 = 1 stop bit
|
548 | ; CHSIZE[2:0] = 011 = 8bit
|
549 | sts USARTE0_CTRLC, temp ; set communication mode and frame format
|
550 |
|
551 | ; schalte Transmitter von USARTE0 an:
|
552 | ldi temp, 0b00001000 ; RXEN = 0 = disable receiver
|
553 | ; TXEN = 1 = enable Transmitter
|
554 | ; CLK2X = 0 = no double transmission speed
|
555 | ; MPCM = 0 = no multiprocessor communication mode
|
556 | ; TXB8 = 0 = no ninth data bit
|
557 | sts USARTE0_CTRLB, temp
|
558 |
|
559 | ret
|
560 |
|
561 |
|
562 | ; ==================================================================================
|
563 | ;
|
564 | ; Warteschleifen
|
565 | ;
|
566 | ; ----------------------------------------------------------------------------------
|
567 |
|
568 | ; Aufruf von wait: Wert in Einheiten von 6,25ms muss in temp3 stehen
|
569 | ; maximaler Wert: 0 (=256), entspricht 1,6s, Wert 160 entspricht 1s
|
570 |
|
571 | wait: push temp3
|
572 | push temp4
|
573 | push count
|
574 | wait1: clr temp4
|
575 | wait2: clr count
|
576 | wait3: dec count
|
577 | brne wait3
|
578 | dec temp4
|
579 | brne wait2
|
580 | dec temp3
|
581 | brne wait1
|
582 | pop count
|
583 | pop temp4
|
584 | pop temp3
|
585 | ret
|
586 |
|
587 | ; Aufruf von shortwait: Wert in Einheiten von 0,025ms muss in temp3 stehen
|
588 | ; maximaler Wert: 0 (=256), entspricht 6,5ms
|
589 |
|
590 | shortwait:
|
591 | push temp3
|
592 | push temp4
|
593 | shortwait1:
|
594 | clr temp4
|
595 | shortwait2:
|
596 | dec temp4
|
597 | brne shortwait2
|
598 | dec temp3
|
599 | brne shortwait1
|
600 | pop temp4
|
601 | pop temp3
|
602 | ret
|
603 |
|
604 | ; ==================================================================================
|
605 |
|
606 | .DSEG
|
607 |
|
608 | Poti_Samples: .BYTE 7168
|
609 |
|
610 | .org (RAMEND-255)
|
611 | ; Speicherort für das Display-Memory muss mit Low-Byte 0 beginnen (neue Seite), sonst funktioniert der Code nicht
|
612 | Display_Memory: .BYTE DISPLAY_SIZE ; Ringspeicher der Display-Daten
|
613 | ; relativer Pointer auf nächstes zu sendende Byte + relativer Ende-Pointer auf letztes zu sendendes Byte:
|
614 | Display_Pointer: .BYTE 2
|