- 12V Akku mit 280 Ah bauen         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 21

Thema: Problem mit Interrupt

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2006
    Beiträge
    21

    Problem mit Interrupt

    Anzeige

    Praxistest und DIY Projekte
    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

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    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 ...

  3. #3
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    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.

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2006
    Beiträge
    21
    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

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    Hi da,
    am besten, du postest mal deinen Code

    mfg

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2006
    Beiträge
    21
    Mach ich!
    Muss euch aber warnen, mir wurde schon öfter gesagt das ich einen katastrophalen Programmierstil hab.

    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
    
    
    
    
    
    
    .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
    Danke
    Stefan

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    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"

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    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

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2006
    Beiträge
    21
    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

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2006
    Beiträge
    21
    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!

Seite 1 von 3 123 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress