Hallo, Ich heiße Leo, habe mich im Offtopic-Forum auch schon
vorgestellt.
Ich bin seit einer Woche dabei, das Programmieren in Assembler zu üben
und habe jetzt mein erstes "größeres" Projekt geschrieben:
An PB2 liegt normalerweise ein Abreisskontakt nach Masse, der beim
Abziehen einen Interrupt auslösen soll, um nach einer gewissen Zeit PB3
auf LOW zu setzen.
Zum Einstellen der Zeit kann man anstatt des Abreisskontakts einen
Taster (schließend nach Masse) anschließen, der die Variable "Zeit" mit
jedem Low-Pegel inkrementiert. Zwischen den einzelnen Abfragen wird
100mS lang gewartet. Der Pull-up ist durch das Programm eingeschaltet.
Beim Abziehen der Stromversorgung, die an PB1 einen Interrupt auslöst,
soll die Variable im EEprom abgelegt werden, der im Schaltplan
eingezeichnete Kondensator besteht aus 1x100n und 1x10µ, was beim
Abziehen der 5 Volt für 10mS bei 2mA reichen sollte.
Nun gibt der Assembler des Avr- Studios verschiedene Fehler aus, von
denen ich einige nicht nachvollziehen kann. Könnt ihr mir da helfen ?
Anbei der Text und ein minimalistischer Schaltplan.
Das Programm ist hier leider ein wenig verschoben, daher auch noch mal
als .asm Datei angehängt.
; setzt nach "Zeit*10" Sekunden PB3 auf 0
; "Zeit" wird bei Abziehen der Stromversorgung in EEprom gespeichert
; alle 100mS inkrementiert ein LOW- Pegel an PB1 "Zeit"
; PROGRAMMIERBARER TIMER:
;5
.include "tn13def.inc"
.def Zeit = r20 ; Register für Variablen festlegen
.def Adresse = r19 ; Register für Variablen festlegen
.def EEmode = r18 ; Register für Variablen festlegen
rjmp Anfang
;10
.org 0x0001 ; Sprungbefehl setzen
rjmp INT0
.org 0x0002 ; Sprungbefehl setzen
rjmp PCINT2
Anfang:
;15
ldi r21,0b00 ; Durch Löschen des 7.Bits (ADEN)
out ADCSRA,r21 ; wird der ADC ausgeschaltet
;cbi ADCSRA,ADEN ; Durch Löschen des 7.Bits (ADEN) den
ADC ausschalten
sbi ddrb,0 ; PortB0 als Ausgang definieren
sbi portb,0 ; PortB0 "High" setzen
;20
sbi portb,2 ; Pull-Up an PortB2 setzen
sbic pinb,2 ; PB2 in r16 einlesen
ldi r16,0
cpi r16,0 ; r16-0
breq Programmieren ; Sprung zu Unterprogramm, wenn
Ergebnis (PortB2)=0 ;25
ldi r17,0x00000011 ; über den Umweg r17
out PCINT2,r17 ; den Pin Change Interrupt auf
steigende Flanke konfigurieren
ldi r17,0x00000000
out INT0,r17 ; INT0 auf LOW-Level konfigurieren
SEI ; Global Interrupts freigeben,
unbedingt vor SLEEP- Befehl ;30
SLEEP ; Sleepmodus wenn PortB2>0
Programmieren:
CLI ; Global Interrupts verhindern(PCINT0
löst auf steigende Flanke an PB2 aus)
clr Zeit ; ÜBERARBEITUNG ERFORDERLICH
sbic pinb,2
;35
ldi r16,0
cpi r16,0
breq Zeit_erhöhen ; Wenn PortB2=0, Zeit inkrementieren
rcall 100mS Warten
SEI ; Interrupts wieder freigeben
;40
ret ; Rücksprung
Zeit_erhöhen:
inc Zeit
ret ; MÖGLICHE FEHLERQUELLE
;45
100mS Warten:
Beginn:
PUSH r16 ; Register sichern
PUSH r17 ; Register sichern
rcall Warten
;50
Warten:
Ldi r16,166
Warten1: ; äußere Schleife
Ldi r17,166
Warten2: ; innere Schleife
;55
dec r17
brne Warten2
dec r16
brne Warten1 ; Summe:83337 Takte = 100,004ms
POP r17 ; Register wiederherstellen
;60
POP r16 ; Register wiederherstellen
ret ; Rücksprung
INT0: ; Interrupt auf Wegfall der
Spannungsversorgung
rcall EEPROM_write ; "Zeit" in EEprom schreiben
reti ; Rücksprung
;65
EEPROM_write: ; Schreibt "Zeit" in EEprom
CLI ; Global Interrupts verhindern, da
Schreibvorgang zeitkritisch
sbic EECR, EEPE ; andere Schreibzugriffe abwarten
rjmp EEPROM_write
ldi EEmode, 0 ; Adresse über das Register r16
;70
out EECR, EEmode ; in das EEprom Control Register
out EEARL,Adresse ; Adresse in EEARL laden
out EEDR, r16 ; Programming Mode in das Register
EEDR
sbi EECR, EEMPE ; Bit EEMPE setzen
sbi EECR, EEPE ; Schreibvorgang starten
;75
SEI ; Global Interrupts freigeben
ret
PCINT2: ; Interrupt auf steigende Flanke an
PortB2
rcall EEPROM_read ; "Zeit" aus EEprom holen, in
"Zeit"(r20) ablegen ;80
mov r21, Zeit ; "Zeit" in Register 21 kopieren
dec r21
brne 1s Warten ; 1s Warten "Zeit" mal ausführen
cbi portb,0 ; PortB0 auf LOW setzen
CLI ; Interrupts verhindern, damit nach
Abtrennen der ;85
reti ; Stromversorgung "Zeit" im EEprom
erhalten bleit(INT0 wird verhindert)
EEPROM_read:
CLI ; Global Interrupts verhindern (lesen
ist zeitkritisch) ;90
sbic EECR, EEPE ; warten bis eventuelle
Schreibzugriffe fertig sind
rjmp EEPROM_read
out EEARL, Adresse ; Adresse in das Register EEARL
kopieren
sbi EECR, EERE ; EERE Bit (EEprom REad) setzen
in Zeit, EEDR ; Daten in "Zeit" kopieren
;95
SEI ; Global Interrupts freigeben
ret
1s_Warten:
ldi r18,0b0A
;100
rcall 100mS Warten
dec r18
brne 1s_Warten
ret
;105
Hier einmal die Fehlermeldungen:
64 : error : Duplicate Label
80 : error : Duplicate Label
39 : error : Garbage at end of line
47 : error : Syntax Error
64 : error : Internal-Label changed between passes -conditonal on
forward reference?
80 : error : Internal-Label changed between passes -conditonal on
forward reference?
84 : error : Garbage at end of line
100 : error : Syntax error
101 : error : Garbage at end of line
102 : error : Garbage at end of line
104 : error : Relative branch out of line
Hi Scmeiss erst mal deine Umlaute aus dem Programm und dann hänge es als Anhang an. MfG Spess
Die Fehlermeldungen sind erst einmal egal, da das Programm vom Ablauf her keine Chance hat, irgendwas Sinnvolles zu machen. Auf jeden Fall am Anfang den Stackpointer initialisieren, sonst funktioniert kein Unterprogramm. Der Sleepmode muss vor dem Sleep Befehl eingestellt werden. ------------- nicht nachvollziehbar --- sbic pinb,2 ; PB2 in r16 einlesen ldi r16,0 cpi r16,0 ; r16-0 breq Programmieren ; Sprung zu Unterprogramm, wenn Ergebnis (PortB2)=0 ;25 --------------------------------------- Zeit_erhöhen: inc Zeit ret *********** ret wohin ? -------------------------------------------- 100mS Warten: Beginn: PUSH r16 ; Register sichern PUSH r17 ; Register sichern rcall Warten ******** ruft Warten auf ** * ;50 Warten: ******* fuehrt nochmal warten aus ? *** Ldi r16,166 Warten1: ; äußere Schleife Ldi r17,166 Warten2: ; innere Schleife ;55 dec r17 brne Warten2 dec r16 brne Warten1 ; Summe:83337 Takte = 100,004ms POP r17 ; Register wiederherstellen ;60 POP r16 ***** 1*gepusht und 2* gepopt, da Warten 2*ausgef. wird* ret ; Rücksprung ---------------------------------------------- alle Interruptroutinen ohne Status Register Sicherung. ---------------------------------------------- PCINT2: ; Interrupt auf steigende Flanke an PortB2 rcall EEPROM_read ; "Zeit" aus EEprom holen, in "Zeit"(r20) ablegen ;80 mov r21, Zeit ; "Zeit" in Register 21 kopieren dec r21 brne 1s Warten ; 1s Warten "Zeit" mal ausführen ********* Verlassen der IR. Routine ohne RETI ********* cbi portb,0 ; PortB0 auf LOW setzen CLI ; Interrupts verhindern, damit nach Abtrennen der ;85 reti ---------------------------------- und zu guter Letzt: Keine Hauptschleife vorhanden und kein sinnvoller Programmablauf erkennbar. Leider sind wohl noch zu viele Schwachstellen vorhanden: keine Programmstruktur Programmablauf, Unterprogramme, Stack Befehle falsch benutzt ... Ich fürchte, Du musst erst mit einfacheren Sachen beginnen. Auch nach Behebung der Fehlermeldungen wird das Programm nicht funktionieren. herrmueller
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.
