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.