- fchao-Sinus-Wechselrichter AliExpress         
Ergebnis 1 bis 8 von 8

Thema: mehrere CALLs im interrupt

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    26.03.2006
    Ort
    WOB
    Beiträge
    630

    mehrere CALLs im interrupt

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo, ich habe ein Problem mit zu vielen Calls im Interrupt.

    Mein Programm ist so gestrickt, dass im Mainloop nix läuft (außer ne LED blinken) und in der ISR eine Nachricht per UART gesendet wird.

    Wenn ich nun nur 1byte sende (2 calls hintereinander) funktioniert es dauerhaft. Wenn ich aber einen Frame aus 6 bytes senden will (so soll die Funktion sein) viele calls und operationen, dann führt er das einmal korrekt aus aber bekommt danach kein Interrupt vom CAN mehr rein. Andere Interrupts gehen danach trotzdem. Er hängt sich auch nicht auf.

    was muss ich da beachten? wieso kann ich nicht so viele calls machen wie ich will?

    Code:
    ;Global Interrupt Vektor
    		ORG 0x0008
    		goto	Isr
    ;******************************************************************************
    ;	Start des Hauptprogramms			 	                        	      *
    ;******************************************************************************
    ;
    Main:
    	ORG		0x0100
    		rcall Init	
    MainLoop:
    		bcf		LATC,5
    		bcf		LATC,4
    		movlw	0x44
    		movwf	xms 
    		call	wxms          ;kurz warten
    	goto MainLoop
    ;
    ;******************************************************************************
    ;	Initialisierung							                                  *
    ;******************************************************************************
    Init:
    	; 8MHz als interne Frequenz
    		movlw	0x70		
    		movwf	OSCCON
    	; Portdirektionen definieren		
    		movlw	0x08
    		movwf 	TRISB
    		movlw	0x8F
    		movwf	TRISC
    		clrf	LATC
    	; Schnittstellenkonfigurationen
    		rcall	canInit
    		rcall	uartInit
    	; Interrupts konfigurieren
    		bsf	INTCON, 7	; Global Int aktivieren
    		bsf	INTCON, 6	; Peripherie Int aktivieren
    		bsf	PIE3, 0		; Interrupt fuer RXB0 aktivieren
    		bsf	PIE1, 5		; Interrupt fuer EUSART receive aktivieren
    	return
    ;
    Isr:
    		btfss	PIR3, 0		; CAN-Nachricht empfangen?
    	goto	uartInt                      ; nein!
    canInt:
    		bsf		LATC,5
    ;CAN Nachricht nach UART senden
    		call	canRecMsg
    		movf	canIDL,w
    		xorlw	0x02
    		btfss	STATUS,Z
    	goto	nloadcanmsg
    loadcanmsg:
    		movlw	0xFF
    		movwf	uartsMsg
    		call	uartSendMsg
    ;		movf	canIDL,w
    ;		iorlw	0x80
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canIDH,w
    ;		andlw	0xF0
    ;		iorlw	0x09
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canIDH,w
    ;		andlw	0x0F
    ;		iorlw	0xA0
    ;		movwf	uartsMsg
    ;		call	uartSendMsg	
    ;		movf	canDLC,w
    ;		iorlw	0xC0
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canDLC,w
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg
    ;		movwf	tempvar
    ;		movf	canMsg0,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg0,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		decf	tempvar
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg
    ;		movf	canMsg1,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg1,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		decf	tempvar
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg	
    ;		movf	canMsg2,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg2,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		decf	tempvar
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg	
    ;		movf	canMsg3,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg3,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		decf	tempvar
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg	
    ;		movf	canMsg4,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg4,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		decf	tempvar
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg	
    ;		movf	canMsg5,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg5,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		decf	tempvar
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg	
    ;		movf	canMsg6,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg6,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		decf	tempvar
    ;		btfsc	STATUS,Z
    ;	goto	nloadcanmsg	
    ;		movf	canMsg7,w
    ;		andlw	0xF0
    ;		swapf	WREG
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    ;		movf	canMsg7,w
    ;		andlw	0x0F
    ;		movwf	uartsMsg
    ;		call	uartSendMsg
    nloadcanmsg:
    		bcf		PIR3,0
    	bra		EndIsr
    uartInt:
    		bsf		LATC,4
    ;UART Nachricht nach CAN senden
    		call	uartRecMsg
    EndIsr:
    	retfie FAST
    Gruß Thomas \/

    Alles über AVR, PIC und CAN
    blog.cc-robotics.de

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    19.11.2007
    Alter
    40
    Beiträge
    140
    Guten Morgen,

    also es wäre noch ganz net zu wissen, um welchen PIC es sich handelt. Dann wäre es noch gut, wenn ich den kompletten Code hätte. So könnte man nachvollziehen, wo du überall hin springst.
    Dann wird jedesmal wenn du eine Sprungmarke callst die Rücksprungandresse im Stack gespeichert. Der Stack ist nicht unendlich groß und irgendwann gibt es dann einen überlauf und du weiß nicht mehr was der PIC macht. Wenn du mit Call in eine Routine springst solltest du auch mit return wieder zurück gehen und dann erst mit goto in diedie nächste Routine callen. Ich weiß das ist nicht immer möglich und sinnvoll, also muss man sich mit dem Datenblatt und dem Stack beschäftigen.

    Hier mal einen Auszug auf dem Datenblatt des 16F87XA

    The PIC16F87XA family has an 8-level deep x 13-bit
    wide hardware stack. The stack space is not part of
    either program or data space and the stack pointer is not
    readable or writable. The PC is PUSHed onto the stack
    when a CALL instruction is executed, or an interrupt
    causes a branch. The stack is POP’ed in the event of a
    RETURN, RETLW or a RETFIE instruction execution.
    PCLATH is not affected by a PUSH or POP operation.
    The stack operates as a circular buffer. This means that
    after the stack has been PUSHed eight times, the ninth
    push overwrites the value that was stored from the first
    push. The tenth push overwrites the second push (and
    so on).


    In diesem Sinne
    Gruß

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    26.03.2006
    Ort
    WOB
    Beiträge
    630
    Ich verwende den PIC18F2685. An den Stack habe ich auch schon gedacht, nur das Programm läuft danach weiter außer dass kein CAN Interrupt mehr kommt. Uartinterrupt funzt trotzdem noch. Die Stacktiefe ist ja wichtig wenn ich mehrere Calls hintereinander aufrufe ohne zurückzuspringen, also rekursiv. Richtig? Wenn ich also eine Funktion recht oft aufrufe sollte das im Stack nicht viel brauchen.

    Gibt es eine Zeitbeschränkung für die ISR? Hier mal mein Code. Danke für die Hilfe!
    Angehängte Dateien Angehängte Dateien
    Gruß Thomas \/

    Alles über AVR, PIC und CAN
    blog.cc-robotics.de

  4. #4
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Hallo T.J.!

    Wenn ein Interrupt ausgelöst wird, muß ein Interrupt-Flag (IF) des Auslösers gelöscht werden, weil so lange das IF gesetzt ist, kann dieser Interrupt nicht mehr ausgelöst werden.

    Allgemain sollte die ISR vor dem nächstem möglichem Interrupt schon beendet werden.

    MfG

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    26.03.2006
    Ort
    WOB
    Beiträge
    630
    Stimmt, danke
    Leider liegt es daran nicht, denn das wird am Ende des Interrupts gemacht. Es sei denn, es gibt Einen Grund dass der Prozessor diesen Befehl bei meinem Code nicht ausführt.
    Aber aufgrund deines Tipps habe ich das eben mal getestet indem ich das Flag manuell per Taster löschen kann, trotzdem wird der Int nur einmal ausgeführt solange mehr als 2 funktionen aufgerufen werden (call).
    Gruß Thomas \/

    Alles über AVR, PIC und CAN
    blog.cc-robotics.de

  6. #6
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    In deiner ISR habe ich die Löschung des IFs nicht gesehen (übersehen?).

    MfG

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    26.03.2006
    Ort
    WOB
    Beiträge
    630
    Ganz unten, bcf PIR3,0

    aber ich habs ich habs! Ich trottel hatte beim Auslesen der CAN botschaft dem CAN Modul gesagt ok, kannst neue Message empfangen. Dann jedoch habe ich ja im Interrupt erst die Nachricht zum PC gesendet bevor ich den Interrupt wieder aktivere. Das hat dem CAN Modul wohl nicht gefallen. Danke für deine Hilfe! Ich komm immer erst drauf, wenn ich n Thread aufgemacht habe
    Gruß Thomas \/

    Alles über AVR, PIC und CAN
    blog.cc-robotics.de

  8. #8
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Ich habe dir gar nicht helfen können. Der Programmentwickler findet seine Fehler am schnellsten, braucht aber manchmal einen kleinen Anstoß.

    Viel Erfolg weiterhin!

    MfG

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad