hast du eventuell vergessen irgendwelche register zu sichern ? sodass sie nach dem interrupt falsche werte tragen ? zur not kurz vor dem branch das interruptenable flag löschen und kurz danach wieder setzen ...
Guten Tag!
Ich arbeite gerade an einer Schaltung die Akkus bis zu einer bestimmten Spannung entladen soll. Der ATMEGA8515, überwacht dabei die Spannung und schaltet ein Relais zum Entladewiderstand ein und aus. Später soll noch ein Display dazu kommen wo man die wichtigsten Werte ablesen kann.
Mein Problem ist das sich die Schaltung nach einer unbestimmten Zeit einfach abschaltet.
Ich verwende 2 Timer, einer zum Entprellen der Ein/Aus-Taste und einmal einen Sekundenzähler der ca. 30 Sekunden warten soll sobald die min.Spannung erreicht wurde und dann nochmals entladen soll.
Hab das Programm jetzt Zeile für Zeile verfolgt und mir ist aufgefallen das wenn ein Timer-Interrup ausgelöst wird und der Rücksprung zufällig auf einen Branch-Befehl trifft, dieser Branch-Befehl ausgeführt wird, obwohl laut dem Compare-Befehl kein Branch stattfinden sollte.
Gibt es dafür irgendeine Lösung?
mfg
Stefan
hast du eventuell vergessen irgendwelche register zu sichern ? sodass sie nach dem interrupt falsche werte tragen ? zur not kurz vor dem branch das interruptenable flag löschen und kurz danach wieder setzen ...
Das hört sich an als würde der Interrupt das Stautsflag verändern. In der Interruptroutine muß man das Statusbyte sichern und am Ende wieder herstellen.
Erstmal danke für die Antworten!
Das mit den Interrupts funktioniert jetzt mal grundsätzlich. Warum weiß ich leider nicht? Hab den ganzen Quellcode in ein neues Projekt kopiert und das Problem war weg.
Leider schaltet die Schaltung immer noch ab, auch wenns jetzt noch etwas länger dauert. Also genauer gesagt springt das Programm in die Funktion die aufgerufen wird man die Stop-Taste drückt. Passiert auch nicht immer zur selben Zeit. Muss aber erst genauer schauen wo jetzt noch ein Problem sein könnte. Passiert halt immer nach ca. 1.000.000 Cycles +/- 200.000. Daher ist es fast nicht möglich das solange Zeile für Zeile anzuschauen.
Ich meld mich wenn ich was weiß!!
Trotzdem danke erst mal.
Stefan
Hi da,
am besten, du postest mal deinen Code
mfg
Mach ich!
Muss euch aber warnen, mir wurde schon öfter gesagt das ich einen katastrophalen Programmierstil hab.
DankeCode:;***************************************************************************** ;* ;* DATEINAME: entlader.asm ;* TITEL : ;* DATUM : 16.6.08 ;* AUTOR : STK ;* VERSION : 1.0 ;* ;* ;***************************************************************************** .include "m8515def.inc" ;--KONSTANTENDEKLARATION--------------------------------------------- ; status register bits .equ CarryFlag = 0 .equ ZeroFlag = 1 .equ NegativeFlag = 2 .equ TwosFlag = 3 .equ SignFlag = 4 .equ HalfCarryFlag = 5 .equ TransferFlag = 6 .equ GlobalFlag = 7 .equ Frequenz = 4000000 .equ Teiler = 4000 ;--VARIABLENDEKLARATION---------------------------------------- .def tmp = R16 ;Temp. Variable .def tmp2 = R17 .def sek_zaehler = R18 .def spg = R19 .def entprell = R20 .CSEG .org 0x0000 rjmp MAIN ;Reset rjmp UnusedInt_ISR ;Ext. Int0 rjmp UnusedInt_ISR ;Ext. Int1 rjmp UnusedInt_ISR ;Timer1 Capture Event rjmp timer ;Timer1 Compare Match A rjmp UnusedInt_ISR ;Timer1 Compare Match B rjmp UnusedInt_ISR ;Timer1 Overflow rjmp UnusedInt_ISR ;Timer0 Overflow rjmp UnusedInt_ISR ;Serial Transfer Complete rjmp UnusedInt_ISR ;USART Rx Complete rjmp UnusedInt_ISR ;USART Data Reg. Empty rjmp UnusedInt_ISR ;USART Tx Complete rjmp UnusedInt_ISR ;Analog Comperator rjmp UnusedInt_ISR ;Ext. Int Request 2 rjmp pause ;Timer0 Compare Match rjmp UnusedInt_ISR ;EEPRom Ready rjmp UnusedInt_ISR ;Store Program memory ready UnusedInt_ISR: reti ;--Hauptprogramm------------------------------------------------ MAIN: ;Stackpointer initialisieren ldi tmp,low (RAMEND) ; RAMEND ist eine im include file vorgegebene Konstante, out SPL,tmp ldi tmp, high(RAMEND) out SPH,tmp rjmp init Main_loop: ;Hauptprogramm ;Akku angesteckt? in tmp2, pina ldi tmp, 0b01001101 ;Akku erkennung ab 3V ;Akku ist angeschloßen cp tmp2,tmp brsh akku_an ;Akku ist nicht angeschloßen cp tmp2, tmp brlo akku_ab rjmp Main_loop; ;--Unterprogramme----------------------------------------------------- akku_ab: ;Ausgabe auf Display ;"Akku" ;"anhängen" rjmp main_loop akku_an: ;Ausgabe auf Display ;SPG:x,xx ;Entl:x,x ;Warte auf Start-Taste in tmp2, pind ;Liest Eingangsport ab andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen ldi tmp, 0b00000001 cp tmp2,tmp breq start ;Ist Bit gesetzt, Spring in die Start- Fkt. ;Warte auf Entladespg senken: ;Warte auf Entladespg erhöhen rjmp main_loop start: ;Akku wurde erkannt und die Starttaste gedrückt ;Start-Taste entprellen clr entprell wh1: ldi tmp, 0b00000010 cp entprell, tmp brlo wh1 clr sek_zaehler ;Entladevorgang starten rjmp entladen_ein entladen_ein: ;Kontrolle ob der Akku noch angeschloßen ist ;Wenn nicht ins Startmenü zurück springen in tmp, pinc ori tmp, 0b00000001 ;Relais aktivieren out portc, tmp ;in tmp2, pina ;ldi tmp, 0b01001101 ;Akku erkennung ab 3V ;cp tmp2, tmp ;brlo entladen_aus ;Akkuspg. überwachen ;Wenn zu niedrig Entladevorgang abbrechen in tmp2, pina ldi tmp, 0b10000000 cp tmp2, tmp brlo entladen_aus ;Warte auf Stop-Taste in tmp2, pind ;Liest Eingangsport ab andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen ldi tmp, 0b00000001 cp tmp2,tmp breq entladen_stop ;Ist Bit gesetzt, Spring in die Start- Fkt. ;Ausgabe auf Display ;A: x,xx ;00:00 rjmp entladen_ein entladen_aus: ;Entladevorgang stoppen weil die Akkuspannung unter ;einem bestimmter Wert gefallen ist in tmp, pinc andi tmp, 0b11111110 out portc, tmp clr sek_zaehler rcall automatik rjmp akku_an automatik: ;Nach 30 Sekunden soll der Entladevorgang erneut ;gestartet werden ldi tmp, 0b00011110 cp sek_zaehler,tmp brsh start ;Schreibe auf Display ;Beendet ;WH in xx ;Warte auf Stop-Taste in tmp2, pind ;Liest Eingangsport ab andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen ldi tmp, 0b00000001 cp tmp2,tmp breq akku_an in tmp2, pina ldi tmp, 0b01001101 ;Akku erkennung ab 3V ;Akku ist nicht angeschloßen cp tmp2, tmp brlo main_loop rjmp automatik entladen_stop: clr entprell wh2: ldi tmp, 0b00000010 cp entprell, tmp brlo wh2 ;Entladevorgang abbrechen in tmp, pinc ldi tmp2, 0b00000001 sub tmp, tmp2 out portc, tmp rjmp main_loop init: ldi spg, 0b01010000 ;vorderen 4 Bit vor Komma, hinteren 4 Bit nach Komma clr sek_zaehler ;Ausgänge setzen ser tmp out ddrc, tmp ;Eingänge setzen clr tmp out ddra, tmp out ddrd, tmp ;Timer1 setzen clr tmp out tccr1a, tmp ldi tmp, 0b00001001 ;nur zu Testzwecken (normal 0b00001101) out tccr1b, tmp ldi tmp, 0b01100001 ;Timer Einstellungen out tIMSK, tmp ldi tmp, HIGH(Frequenz / Teiler) out ocr1ah, tmp ldi tmp, LOW(Frequenz / Teiler) out ocr1al, tmp ;Timer0 setzen ldi tmp, 0b00000001 ;nur zu Testzwecken (normal 0b00000101) out tccr0, tmp ldi tmp, 0b01001110 out ocr0, tmp sei rjmp main_loop ;*********Interrupt*********** ;Zähler für die Sekundenzählung timer: inc sek_zaehler reti ;Zähler für die Entprellung pause: inc entprell reti
Stefan
Hi Stefan,
wie meine Vorgänger schon sagten, du musst das Status Register retten.
Ich will dir nicht auf den Schlips treten wenn ich frage ob du weißt, was das ist?
Ich hab die entsprechenden Zeilen in den ISR´s geändert und das bei den Registerdefinitionen eingefügt : .def sreg_save = r21
Schon einfache Operationen auf Register "effecten" das Statusregister, was einen vor der ISR gemachten Vergleich verfälschen kann.
Z.B. wird das Statusbit "S" verändert, das für manche branches als Initiator dient.
mfg,
The Man
Code:;***************************************************************************** ;* ;* DATEINAME: entlader.asm ;* TITEL : ;* DATUM : 16.6.08 ;* AUTOR : STK ;* VERSION : 1.0 ;* ;* ;***************************************************************************** .include "m8515def.inc" ;--KONSTANTENDEKLARATION--------------------------------------------- ; status register bits .equ CarryFlag = 0 .equ ZeroFlag = 1 .equ NegativeFlag = 2 .equ TwosFlag = 3 .equ SignFlag = 4 .equ HalfCarryFlag = 5 .equ TransferFlag = 6 .equ GlobalFlag = 7 .equ Frequenz = 4000000 .equ Teiler = 4000 ;--VARIABLENDEKLARATION---------------------------------------- .def tmp = R16 ;Temp. Variable .def tmp2 = R17 .def sek_zaehler = R18 .def spg = R19 .def entprell = R20 .def sreg_save = r21 .CSEG .org 0x0000 rjmp MAIN ;Reset rjmp UnusedInt_ISR ;Ext. Int0 rjmp UnusedInt_ISR ;Ext. Int1 rjmp UnusedInt_ISR ;Timer1 Capture Event rjmp timer ;Timer1 Compare Match A rjmp UnusedInt_ISR ;Timer1 Compare Match B rjmp UnusedInt_ISR ;Timer1 Overflow rjmp UnusedInt_ISR ;Timer0 Overflow rjmp UnusedInt_ISR ;Serial Transfer Complete rjmp UnusedInt_ISR ;USART Rx Complete rjmp UnusedInt_ISR ;USART Data Reg. Empty rjmp UnusedInt_ISR ;USART Tx Complete rjmp UnusedInt_ISR ;Analog Comperator rjmp UnusedInt_ISR ;Ext. Int Request 2 rjmp pause ;Timer0 Compare Match rjmp UnusedInt_ISR ;EEPRom Ready rjmp UnusedInt_ISR ;Store Program memory ready UnusedInt_ISR: reti ;--Hauptprogramm------------------------------------------------ MAIN: ;Stackpointer initialisieren ldi tmp,low (RAMEND) ; RAMEND ist eine im include file vorgegebene Konstante, out SPL,tmp ldi tmp, high(RAMEND) out SPH,tmp rjmp init Main_loop: ;Hauptprogramm ;Akku angesteckt? in tmp2, pina ldi tmp, 0b01001101 ;Akku erkennung ab 3V ;Akku ist angeschloßen cp tmp2,tmp brsh akku_an ;Akku ist nicht angeschloßen cp tmp2, tmp brlo akku_ab rjmp Main_loop; ;--Unterprogramme----------------------------------------------------- akku_ab: ;Ausgabe auf Display ;"Akku" ;"anhängen" rjmp main_loop akku_an: ;Ausgabe auf Display ;SPG:x,xx ;Entl:x,x ;Warte auf Start-Taste in tmp2, pind ;Liest Eingangsport ab andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen ldi tmp, 0b00000001 cp tmp2,tmp breq start ;Ist Bit gesetzt, Spring in die Start- Fkt. ;Warte auf Entladespg senken: ;Warte auf Entladespg erhöhen rjmp main_loop start: ;Akku wurde erkannt und die Starttaste gedrückt ;Start-Taste entprellen clr entprell wh1: ldi tmp, 0b00000010 cp entprell, tmp brlo wh1 clr sek_zaehler ;Entladevorgang starten rjmp entladen_ein entladen_ein: ;Kontrolle ob der Akku noch angeschloßen ist ;Wenn nicht ins Startmenü zurück springen in tmp, pinc ori tmp, 0b00000001 ;Relais aktivieren out portc, tmp ;in tmp2, pina ;ldi tmp, 0b01001101 ;Akku erkennung ab 3V ;cp tmp2, tmp ;brlo entladen_aus ;Akkuspg. überwachen ;Wenn zu niedrig Entladevorgang abbrechen in tmp2, pina ldi tmp, 0b10000000 cp tmp2, tmp brlo entladen_aus ;Warte auf Stop-Taste in tmp2, pind ;Liest Eingangsport ab andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen ldi tmp, 0b00000001 cp tmp2,tmp breq entladen_stop ;Ist Bit gesetzt, Spring in die Start- Fkt. ;Ausgabe auf Display ;A: x,xx ;00:00 rjmp entladen_ein entladen_aus: ;Entladevorgang stoppen weil die Akkuspannung unter ;einem bestimmter Wert gefallen ist in tmp, pinc andi tmp, 0b11111110 out portc, tmp clr sek_zaehler rcall automatik rjmp akku_an automatik: ;Nach 30 Sekunden soll der Entladevorgang erneut ;gestartet werden ldi tmp, 0b00011110 cp sek_zaehler,tmp brsh start ;Schreibe auf Display ;Beendet ;WH in xx ;Warte auf Stop-Taste in tmp2, pind ;Liest Eingangsport ab andi tmp2, 0b00000001 ;Nur das Start-tasten-Bit einlesen ldi tmp, 0b00000001 cp tmp2,tmp breq akku_an in tmp2, pina ldi tmp, 0b01001101 ;Akku erkennung ab 3V ;Akku ist nicht angeschloßen cp tmp2, tmp brlo main_loop rjmp automatik entladen_stop: clr entprell wh2: ldi tmp, 0b00000010 cp entprell, tmp brlo wh2 ;Entladevorgang abbrechen in tmp, pinc ldi tmp2, 0b00000001 sub tmp, tmp2 out portc, tmp rjmp main_loop init: ldi spg, 0b01010000 ;vorderen 4 Bit vor Komma, hinteren 4 Bit nach Komma clr sek_zaehler ;Ausgänge setzen ser tmp out ddrc, tmp ;Eingänge setzen clr tmp out ddra, tmp out ddrd, tmp ;Timer1 setzen clr tmp out tccr1a, tmp ldi tmp, 0b00001001 ;nur zu Testzwecken (normal 0b00001101) out tccr1b, tmp ldi tmp, 0b01100001 ;Timer Einstellungen out tIMSK, tmp ldi tmp, HIGH(Frequenz / Teiler) out ocr1ah, tmp ldi tmp, LOW(Frequenz / Teiler) out ocr1al, tmp ;Timer0 setzen ldi tmp, 0b00000001 ;nur zu Testzwecken (normal 0b00000101) out tccr0, tmp ldi tmp, 0b01001110 out ocr0, tmp sei rjmp main_loop ;*********Interrupt*********** ;Zähler für die Sekundenzählung timer: in sreg_save,SREG inc sek_zaehler out SREG,sreg_save reti ;Zähler für die Entprellung pause: in sreg_save,SREG inc entprell out SREG,sreg_save reti
Chuck Norris kann Windows Vista auf einem Atmel in Assembler implementieren!
Chuck Norris coded mit 3 Tasten:"1","0" und "compile"
kann es sein das start und stopp-taste bei dir ein und dasselbe sind ? beide liegen auf bit 0 von PIND ???
brsh start
weis ja nicht genau was das bewirkt, bis kein assemlberspezi, ist in deiner automatikschleife, womöglich änderst du irgendwo deine "entprell" in der startfunktion ungewollt ? tut mir echt leid, ich kann kein assembler(VIEL ZU LANG HER) aber wenn ich so drübergehe sind mir die 2 sachen halt aufgefallen
Ja das mit dem Taster stimmt. Es soll nur einen Taster für Start und Stop geben.
Ich vermute mal du meinst den "brsh start"-Befehl in der Automatik- Funktion.
Da wird die Variable in der die Sekunden hochgezählt werden mit einem von mir festgelegten Wert (30) vergliechen. Sobald der Sekundenzähler gleich oder höher (brsh) ist springt das Programm zurück zum Start der Entladefunktion um noch einen Entladeversuch durch zu führen
mfg
Hab das mal eine weile Laufen lassen. Nicht nur das es in die Stop-Funktion springt, es springt später auch wieder in die Start-Funktion.
Die Branch-Befehle werden aus irgend einem mir noch unklaren Grund ausgeführt obwohl die Bedingung nicht erfüllt werden.
Hab es weiter eingegrenzt. Es passiert nur wenn der Timer1 Interrupt aktiv ist!!
Ich versteh aber einfach nicht warum!
Lesezeichen