1 | .NOLIST
|
2 | .INCLUDE "m8def.inc"
|
3 | .LIST
|
4 |
|
5 | .DEF temp1 = r16
|
6 | .DEF temp2 = r17
|
7 | .DEF alt = r18 ;alter Zustand(Drehgeber) allgemein
|
8 | .DEF cnt = r19 ;der Zähler(Drehgeber) allgemein
|
9 | .DEF pos = r20 ;Position(Drehgeber) allgemein
|
10 | .DEF spg = r21 ;Spannung der mini-PV-module
|
11 |
|
12 |
|
13 | .DEF Maske = r2 ;Maske für Drehgeber allgemein
|
14 | .DEF Teiler = r3 ;Teiler für Drehgeber allgemein
|
15 | .DEF pos_klein = r4 ;Position der Kleinanlage (auf 3,6 Grad genau)
|
16 | .DEF pos_PV = r5 ;Position der PV-Anlage
|
17 | .DEF cnt_klein = r6 ;der Zähler--klein
|
18 | .DEF cnt_PV = r7 ;der Zähler--PV
|
19 | .DEF alt_PV = r8 ;alter Zustand Drehgeber-PV-Anlage
|
20 | .DEF alt_klein = r9 ;alter Zustand Drehgeber-Kleinanlage
|
21 | .DEF sec4 = r10
|
22 | .DEF wind = r11
|
23 | .DEF myflag = r12 ;Bit 0 - Intervall Nachführung
|
24 | ;Bit 1 - Intervall Kleinanlage
|
25 | ;Bit 6 - alter Zustand Windmesser
|
26 | ;Bit 7 - Intervall Windmesser (4s)
|
27 |
|
28 | .def prescaler = r22
|
29 | .def sec = r23
|
30 | .def min = r24
|
31 | .def hour = r25
|
32 | ;.def day = r26
|
33 |
|
34 | ;Konstanten
|
35 |
|
36 | .EQU Kanal_spg = 0b11000000 ;Kanal für ADC,Spannung-module
|
37 | .EQU Kanal_wind = 0b11000001 ;Kanal für ADC, Windrichtung
|
38 | .EQU Teiler_klein = 4 ;Prescaler Drehgeber
|
39 | .EQU Teiler_PV = 4 ;Prescaler Drehgeber
|
40 | .EQU Maske_klein= 0b00001100 ;Maske für Drehgeber-Anschluß
|
41 | .EQU Maske_PV = 0b00110000
|
42 | .EQU MaxWind = 100 ;maximale windgeschwindigkeit
|
43 | .EQU xtal = 16000000 ;Taktfrequenz
|
44 | .EQU debounce = 256 ;
|
45 | .EQU remainder = xtal - xtal / debounce * debounce
|
46 | .EQU wind_int = 4
|
47 | .EQU nachfue_int= 15
|
48 | .EQU sichpos_int= 30
|
49 |
|
50 |
|
51 | .CSEG
|
52 | .ORG 0x00 ;Reset Handler
|
53 | RJMP init
|
54 |
|
55 | ; .ORG INT0addr ; External Interrupt0 Vector Address
|
56 | ; RETI
|
57 |
|
58 | .ORG INT1addr ; External Interrupt1 Vector Address
|
59 | RJMP windcount
|
60 |
|
61 | ; .ORG OC2addr ; Output Compare2 Interrupt Vector Address
|
62 | ; RETI
|
63 |
|
64 | ; .ORG OVF2addr ; Overflow2 Interrupt Vector Address
|
65 | ; RETI
|
66 |
|
67 | ; .ORG ICP1addr ; Input Capture1 Interrupt Vector Address
|
68 | ; RETI
|
69 |
|
70 | .ORG OC1Aaddr ; Output Compare1A Interrupt Vector Address
|
71 | RJMP Timer1
|
72 |
|
73 | ; .ORG OC1Baddr ; Output Compare1B Interrupt Vector Address
|
74 | ; RETI
|
75 | ;
|
76 | ; .ORG OVF1addr ; Overflow1 Interrupt Vector Address
|
77 | ; RETI
|
78 |
|
79 | ; .ORG OVF0addr ; Overflow0 Interrupt Vector Address
|
80 | ; RETI
|
81 |
|
82 | ; .ORG SPIaddr ; SPI Interrupt Vector Address
|
83 | ; RETI
|
84 |
|
85 | ; .ORG URXCaddr ; USART Receive Complete Interrupt Vector Address
|
86 | ; RETI
|
87 |
|
88 | ; .ORG UDREaddr ; USART Data Register Empty Interrupt Vector Address
|
89 | ; RETI
|
90 |
|
91 | ; .ORG UTXCaddr ; USART Transmit Complete Interrupt Vector Address
|
92 | ; RETI
|
93 |
|
94 | ; .ORG ADCCaddr ; ADC Interrupt Vector Address
|
95 | ; RETI
|
96 |
|
97 | ; .ORG ERDYaddr ; EEPROM Interrupt Vector Address
|
98 | ; RETI
|
99 |
|
100 | ; .ORG ACIaddr ; Analog Comparator Interrupt Vector Address
|
101 | ; RETI
|
102 |
|
103 | ; .ORG TWIaddr ; Irq. vector address for Two-Wire Interface
|
104 | ; RETI
|
105 |
|
106 | ; .ORG SPMaddr ; SPM complete Interrupt Vector Address
|
107 | ; RETI
|
108 |
|
109 | ;.ORG SPMRaddr ; SPM complete Interrupt Vector Address
|
110 | ; RETI
|
111 |
|
112 |
|
113 | windcount: ;wird bei Interrupt-Auslösung
|
114 | push temp1
|
115 | mov temp1, wind
|
116 | INC temp1 ;an PD3 ausgeführt
|
117 | mov wind, temp1
|
118 | pop temp1
|
119 | RETI
|
120 |
|
121 | Timer1:
|
122 | push temp1
|
123 | in temp1, sreg
|
124 | ;************************************************************************/
|
125 | ;* Insert Key Debouncing Here */
|
126 | ;************************************************************************/
|
127 |
|
128 | ldi temp2, high( xtal / debounce - 1 )
|
129 | out ocr1ah, temp2
|
130 | ldi temp2, low( xtal / debounce - 1 )
|
131 | out ocr1al, temp2
|
132 |
|
133 | dec prescaler
|
134 | brne _oci1
|
135 |
|
136 | ldi prescaler, debounce
|
137 | INC sec
|
138 |
|
139 | ldi temp2, high( xtal / debounce + remainder - 1 )
|
140 | out ocr1ah, temp2
|
141 | ldi temp2, low( xtal / debounce + remainder - 1 )
|
142 | out ocr1al, temp2
|
143 | _oci1:
|
144 | out sreg, temp1
|
145 | pop temp1
|
146 | reti
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 | init:
|
154 | ;********************************* stackpointer initialisieren
|
155 |
|
156 | ldi temp1, LOW(RAMEND) ; LOW-Byte der untersten RAM-adresse
|
157 | out SPL, temp1
|
158 | ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
|
159 | out SPH, temp1
|
160 |
|
161 | ;********************************* AD-Wandler 16MHz / 200kHz = 80 mind.
|
162 |
|
163 | ldi temp1,0b00000111
|
164 | out ADCSR,temp1
|
165 |
|
166 | cbi ADCSR,ADIE
|
167 |
|
168 | sbi ADCSR,ADEN ;AD einschalten/aktivieren
|
169 |
|
170 |
|
171 | ;********************************************************* Ein-Ausgange festlegen
|
172 |
|
173 |
|
174 | ldi TEMP1,0b11110010 ;0=input, 1=output
|
175 | out DDRD,TEMP1
|
176 |
|
177 | ldi TEMP1,0b10001000 ; pull-up resistors(1) on inputs
|
178 | out PORTD,TEMP1
|
179 |
|
180 | ldi temp1, 0b00111111 ;Port B
|
181 | out DDRB, temp1
|
182 |
|
183 | ldi temp1, 0b00000000 ;Port C
|
184 | out DDRC, temp1
|
185 |
|
186 |
|
187 |
|
188 | ;*************************************************************************** RTC
|
189 |
|
190 | ldi temp1, 1<<WGM12^1<<CS10
|
191 | out TCCR1B, temp1
|
192 |
|
193 | ldi temp1, high( xtal / debounce - 1 )
|
194 | out ocr1ah, temp1
|
195 | ldi temp1, low( xtal / debounce - 1 )
|
196 | out ocr1al, temp1
|
197 | out tcnt1l, temp1
|
198 | ldi prescaler, debounce
|
199 |
|
200 | ldi temp1, 1<<OCIE1A
|
201 | out TIMSK, temp1
|
202 |
|
203 | ;******************************************************************* externe Interrupts
|
204 | ldi temp1, 0b00001010 ;INT0 und INT1 konfigurieren-fallende Flanke
|
205 | out MCUCR, temp1
|
206 |
|
207 | ldi temp1, 0b11000000 ;INT0 und INT1 aktivieren
|
208 | out GICR, temp1
|
209 |
|
210 |
|
211 | sei
|
212 |
|
213 | ;******************************************************************* Hauptprogramm
|
214 | hauptprog:
|
215 |
|
216 | NOP
|
217 |
|
218 | ;******* Drehgeber einmal einlesen
|
219 |
|
220 | ldi temp1, Maske_klein ;Maske festlegen
|
221 | MOV Maske, temp1
|
222 | IN temp1,PINC ;einmal den aktuellen PortZustand laden
|
223 | ANDI temp1,Maske_klein ;Drehgeber-Bits maskieren
|
224 | RCALL schieben01 ;und in 01-Position schieben
|
225 | MOV alt_klein, temp1
|
226 |
|
227 | ldi temp1, Maske_PV ;und nochmal für anderen Drehgeber
|
228 | MOV Maske, temp1
|
229 | IN temp1,PINC
|
230 | AND temp1, Maske
|
231 | RCALL schieben01
|
232 | MOV alt_PV, temp1
|
233 |
|
234 |
|
235 | clr pos_klein ;Position beider Drehgeber reset
|
236 | clr pos_PV
|
237 | clr cnt_klein
|
238 | clr cnt_PV
|
239 |
|
240 | rcall lcd_init ;Display initialisieren
|
241 | rcall lcd_clear ;Display löschen
|
242 |
|
243 | ldi sec, 0 ;RTC mit 0 laden
|
244 | ldi min, 0
|
245 | ldi hour,0
|
246 |
|
247 | rjmp main
|
248 |
|
249 | ;************************************************************ Sicherheitsposition
|
250 | sichpos:
|
251 | SBIC PORTD,7 ;Notrelais schon an ??
|
252 | rjmp notrelais_an
|
253 | rjmp main
|
254 |
|
255 | notrelais_an:
|
256 | CBI PORTD, 7 ;Notrelais an PD7 einschalten (0)
|
257 |
|
258 |
|
259 |
|
260 |
|
261 |
|
262 | ;****************** Normalfall
|
263 | main:
|
264 |
|
265 | ;Intervalle
|
266 |
|
267 | cpi sec, wind_int
|
268 | BREQ myflag7
|
269 | ;cpi min, nachfue_int
|
270 | ;BREQ myflag0
|
271 | rjmp second
|
272 |
|
273 | myflag7:MOV temp1, myflag
|
274 | SBR temp1, 7
|
275 | MOV myflag, temp1
|
276 | rjmp second
|
277 |
|
278 | myflag0:MOV temp1, myflag
|
279 | SBR temp1, 0
|
280 | MOV myflag, temp1
|
281 | rjmp second
|
282 |
|
283 | ;****RTC
|
284 | second:
|
285 | cpi sec, 60 ;----second
|
286 | breq minute
|
287 | rjmp main_weiter
|
288 |
|
289 | minute: clr sec ;minute
|
290 | inc min
|
291 | cpi min, 60
|
292 | breq hour
|
293 | rjmp main_weiter
|
294 |
|
295 | hour: clr min ;hour
|
296 | inc hour
|
297 | cpi hour, 24
|
298 | breq day
|
299 | rjmp main_weiter
|
300 |
|
301 | day: clr hour ;day
|
302 | nop
|
303 | rjmp main_weiter
|
304 |
|
305 |
|
306 |
|
307 |
|
308 | main_weiter:
|
309 |
|
310 | RCALL windmessung ;windrichtg/geschw
|
311 | RCALL kleinanlage ;Beste Position bestimmen
|
312 | ;RCALL nachfuehrung ;zu bestem Wert nachführen
|
313 | ;RCALL speichern ;Werte speichern
|
314 | ;RCALL ausgeben ;Anzeige am LCD
|
315 | ;RCALL messen
|
316 |
|
317 | RJMP main
|
318 |
|
319 |
|
320 |
|
321 |
|
322 |
|
323 |
|
324 | cpi spg,MaxWind ;Windgeschw. zu groß ?
|
325 | BRSH sichpos
|
326 |
|
327 | ;LDI temp1, 0x00 ;verzögerung abgelaufen ?? dann vergleich und evtl abschalten
|
328 | ;cpi temp1, sichpos_int
|
329 | BRLO sichpos_aus
|
330 | rjmp main
|
331 |
|
332 | sichpos_aus:
|
333 | SBI PORTD, 7 ;Notrelais an PD7 ausschalten (1)
|
334 | rjmp main
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 |
|
343 |
|
344 | ;******************************************************************* ADC-Wandlung
|
345 | analog_digital:
|
346 |
|
347 | ;Single-Mode
|
348 |
|
349 | Main_Single: sbi ADCSR,ADSC ;Start Wandlung
|
350 | ;das ADSC-Flag löscht sich
|
351 | ;selbst nach der Wandlung
|
352 | ;man kann es auch für busy? verwenden
|
353 |
|
354 | AD_busy_: sbis ADCSR,ADIF ;Flag, busy?
|
355 | rjmp AD_busy_ ;springt raus, wenn fertig
|
356 |
|
357 |
|
358 |
|
359 | Lesen_Single: in temp1,ADCL ;Das Ergebnis steht in temp1,temp2
|
360 | in temp2,ADCH
|
361 |
|
362 | ;Sollten nur 8 Bit = 256 Schritte notwendig sein, dann wie folgt:
|
363 |
|
364 | ;Auf256_: ror temp2 ;xxxxxxxN c=N
|
365 | ; ror temp1 ;Nnnnnnnn c=n
|
366 | ; ror temp2 ;xxxxxxxx c=N
|
367 | ; ror temp1 ;NNnnnnnn c=n
|
368 |
|
369 | ; mov spg, temp1 ;Das Ergebnis steht in spg
|
370 |
|
371 | ret
|
372 |
|
373 |
|
374 | ;******************************************************************** Nachführung
|
375 | nachfuehrung:
|
376 |
|
377 | sbrs myflag, 0 ;intervall abgelaufen ?
|
378 | ret ;zurück, wenn nicht
|
379 |
|
380 |
|
381 | ;**************** Werte für Drehgeber_PV zuweisen
|
382 | ;Maske ---welcher Drehgeber wird verwendet
|
383 | ;alt ---alter Drehgeber-zustand
|
384 | ;cnt --- alter counter-stand
|
385 | ;Teiler ---Teiler
|
386 | ;pos ---position des Drehgebers
|
387 |
|
388 |
|
389 |
|
390 | ldi temp1, Maske_PV
|
391 | mov Maske, temp1
|
392 | mov alt, alt_PV
|
393 | mov cnt, cnt_PV
|
394 | ldi temp1, Teiler_PV
|
395 | mov Teiler, temp1
|
396 | mov pos, pos_PV
|
397 |
|
398 | RCALL position ;position bestimmen
|
399 |
|
400 | mov pos_PV, pos
|
401 | mov cnt_PV, cnt
|
402 | mov alt_PV, alt
|
403 |
|
404 | cp pos_klein, pos_PV ;Positionsvergleich
|
405 | BRNE weiter2 ;gleich ?
|
406 | clr temp1 ;wenn ja, dann rechts- und linkslauf ausschalten
|
407 | out portD, temp1 ;ansonsten zu weiter2
|
408 | ret
|
409 | weiter2:
|
410 | BRLO links
|
411 | BRSH rechts
|
412 |
|
413 |
|
414 |
|
415 | links:
|
416 | SBIS portD,4 ;schon an ??
|
417 | rjmp an_links
|
418 | ret
|
419 | an_links:
|
420 | ldi temp1, 0b00010000 ;Relais für linkslauf anschalten
|
421 | out portD, temp1
|
422 | ret
|
423 |
|
424 |
|
425 |
|
426 |
|
427 | rechts:
|
428 | SBIS portD,5 ;schon an ??
|
429 | rjmp an_rechts
|
430 | ret
|
431 | an_rechts:
|
432 | ldi temp1, 0b00100000 ;Relais für rechtslauf anschalten
|
433 | out portD, temp1
|
434 | ret
|
435 |
|
436 |
|
437 | ;******************************************************************* Kleinanlage
|
438 | kleinanlage:
|
439 |
|
440 | sbrs myflag, 1 ;intervall abgelaufen ?
|
441 | rjmp wischer_aus
|
442 | rjmp messen
|
443 |
|
444 | wischer_aus:
|
445 | CBI PORTD, 7 ;wischermotor ausschalten
|
446 | RET
|
447 |
|
448 | messen:
|
449 | ;Spannungsmessung der RWE-Schott mini-Solarmodule
|
450 | ;mit
|
451 | ;Leerlaufpannung ;4,9V
|
452 | ;Lastspannung max :3,6V
|
453 | ;Pmax ;0,1W
|
454 | ;Kurzschlussstrom ;35mA
|
455 | ;Laststrom max :27mA
|
456 | ;
|
457 | ;Eingang ADC0 an PC0
|
458 |
|
459 | ldi temp1,Kanal_spg ;Kanal für ADC auswählen ;
|
460 | out ADMUX,temp1 ;
|
461 | rcall analog_digital ;Wandlung durchführen
|
462 |
|
463 | ;Ergebnis in ADCL,ADCH
|
464 |
|
465 | ;**************** Werte für Drehgeber_klein zuweisen
|
466 | ;Maske ---welcher Drehgeber wird verwendet
|
467 | ;alt ---alter Drehgeber-zustand
|
468 | ;cnt --- alter counter-stand
|
469 | ;Teiler ---Teiler
|
470 | ;pos ---position des Drehgebers
|
471 |
|
472 |
|
473 | ldi temp1, Maske_klein
|
474 | mov Maske, temp1
|
475 | mov alt, alt_klein
|
476 | mov cnt, cnt_klein
|
477 | ldi temp1, Teiler_klein
|
478 | mov Teiler, temp1
|
479 | mov pos, pos_klein
|
480 |
|
481 | RCALL position ;position bestimmen
|
482 |
|
483 | mov pos_klein, pos
|
484 | mov cnt_klein, cnt
|
485 | mov alt_klein, alt
|
486 |
|
487 | SBIS portD,6 ;wischer schon an ??
|
488 | rjmp wischer_an
|
489 | ret
|
490 |
|
491 | wischer_an:
|
492 | SBI PORTD, 6 ;wischer anschalten
|
493 | RET
|
494 |
|
495 |
|
496 | ;****************************************************************** Windmessung
|
497 | windmessung:
|
498 | ;************ Geschwindigkeit
|
499 |
|
500 | ;nop
|
501 | ;ret
|
502 |
|
503 | SBRS myflag, 7 ; vier Sekunden vergangen ?
|
504 | RET
|
505 | rjmp calc
|
506 | calc:
|
507 | lsr wind ;wind/4= Hz, da pro Sekunde
|
508 | lsr wind
|
509 | RCALL ausgeben
|
510 | clr wind
|
511 |
|
512 | MOV temp1, myflag ;Reset des 4-Sekunden Zählers
|
513 | CBR temp1, 7
|
514 | MOV myflag, temp1
|
515 |
|
516 | RET
|
517 | RJMP windrichtung
|
518 |
|
519 |
|
520 |
|
521 |
|
522 | ;************ windrichtung
|
523 |
|
524 | windrichtung:
|
525 | ldi temp1,Kanal_wind ;Kanal für ADC auswählen ;
|
526 | out ADMUX,temp1 ;
|
527 |
|
528 | RCALL analog_digital ;Wandlung durchführen
|
529 | ;Ergebnis in temp1,temp2
|
530 |
|
531 | ;vergleich mit Tabelle-------für Richtungsangabe
|
532 |
|
533 |
|
534 | RET
|
535 |
|
536 | ;;;;windmessung ENDE
|
537 |
|
538 | ;*********************************************************** Speichern der Daten
|
539 | speichern:
|
540 | sbrs myflag, 0 ;intervall abgelaufen ?
|
541 | rjmp abspeichern
|
542 | ret
|
543 |
|
544 | abspeichern:
|
545 |
|
546 | ;Zeit + höchste Windgeschw + Richtg+ beste Pos+Spg
|
547 |
|
548 | ;clr flag
|
549 |
|
550 | nop
|
551 |
|
552 | ret
|
553 |
|
554 |
|
555 | ;****************************************************************** Display/UART
|
556 | ausgeben:
|
557 | rcall lcd_home
|
558 |
|
559 | hex2bcd:
|
560 | push sec
|
561 | mov sec, myflag
|
562 | push r17
|
563 | push r18
|
564 | ldi r18, -1 + '0'
|
565 | _bcd1: inc r18
|
566 | subi sec, 100
|
567 | brcc _bcd1
|
568 | ldi r17, 10 + '0'
|
569 | _bcd2: dec r17
|
570 | subi sec, -10
|
571 | brcs _bcd2
|
572 | subi sec, -'0'
|
573 | ;ret
|
574 |
|
575 | mov temp1,r18
|
576 | rcall lcd_data
|
577 |
|
578 | mov temp1,r17
|
579 | rcall lcd_data
|
580 |
|
581 | mov temp1,sec
|
582 | rcall lcd_data
|
583 |
|
584 | pop r18
|
585 | pop r17
|
586 | pop sec
|
587 |
|
588 | ;------------
|
589 |
|
590 | ;rcall lcd_secondline
|
591 | ldi ZH,high(2*ausgabe) ;Lade oberen Teil der
|
592 | ;ByteAdresse in ZH
|
593 | ldi ZL,low(2*ausgabe) ;Lade unteren Teil der
|
594 | ;ByteAdresse in ZL
|
595 | rcall lcd_out ;Text ausgeben
|
596 |
|
597 | ret
|
598 |
|
599 |
|
600 | ;********************************************************************** Tabellen
|
601 |
|
602 | ausgabe:
|
603 | .db " Anzeige funktioniert!",0
|
604 |
|
605 |
|
606 | .NOLIST
|
607 | .INCLUDE "routines.asm"
|
608 | .INCLUDE "position.asm"
|
609 | .LIST
|