Probleme mit Interrupts bei PIC16F688

Gast #7099347
Lesenswert?

Hallo zusammen,
nun bin ich scheinbar doch wieder auf die Hilfe aus dem großen weiten 
Internetz angewiesen.
Folgende Grundinfos: PIC16F688, Assembler, pic-as in MPLAB X v6.00
Das Problem: Ich bekomme einfach keinerlei Interrupts hin...
Z.B. mit Timer1: Der Timer selbst läuft und setzt auf das TMR1IF bit 
(lässt sich ja einfach durch dauerhaftes Prüfen herausfinden), alle 
"Anzeigeräte" und deren Software (LED-Ansteuerung, etc.) läuft auch. GIE 
und PEIE sind gesetzt.
Das Zwischenspeichern des W- und STATUS-Registers ist meine ich zwar 
auch noch nicht richtig, ist im Moment aber noch unerheblich. Die ISR 
ist mit dem Linkerbefehl -pInterrupt=0x04 an die richtige Position 
gesetzt.
Die ISR lautet:
1
PSECT Interrupt, class=CODE, delta=2
2
 ISR:
3
    BANKSEL WREG_Temp
4
    MOVWF WREG_Temp      ;WREG zwischenspeichern
5
    BANKSEL STATUS
6
    MOVF STATUS, 0      ;STATUS zwischenspeichern
7
    MOVWF Status_Temp
8
    
9
    BANKSEL INTCON
10
    BTFSC INTCON, 3      ;Prüfen ob RAIE gesetzt
11
    BTFSS INTCON, 0      ;Prüfen ob RAIF gesetzt
12
    goto $+2
13
    goto ISR_PORTA
14
    
15
    BANKSEL PIE1
16
    BTFSS PIE1, 0      ;Prüfen ob TMR1IE gesetzt
17
    goto $+4
18
    BANKSEL PIR1
19
    BTFSC PIR1, 0      ;Prüfen ob TMR1IF gesetzt
20
    goto ISR_Timer1      ;Gehe zu ISR_Timer1
21
    
22
    goto EndeInterrupt
23
    
24
ISR_Timer1:
25
    BCF PIR1, 0                         ;TMR1IF löschen
26
    BANKSEL PORTA
27
    MOVLW PORTA                         ;PORTA ins WREG laden
28
    XORLW 00100000B                     ;LED an RA5 ändern
29
    MOVWF PORTA                         ;Wieder in PORTA laden
30
    goto EndeInterrupt
31

32
ISR_PORTA:
33
    BANKSEL PORTA
34
    MOVF PORTA, 0
35
    BANKSEL INTCON
36
    BCF INTCON, 0
37
    LEDRotAN
38
    goto EndeInterrupt
39
       
40
    
41
 EndeInterrupt:
42
    MOVF Status_Temp, 0      ;Zwischengespeicherten Status wieder laden
43
    MOVWF STATUS
44
    MOVF WREG_Temp, 0      ;Zwischengespeichertes WREG wieder laden
45
    RETFIE
46
 ;Ende Interrupt

Und jetzt weiß ich mir nicht mehr zu helfen und hoffe, dass die 
Gruppenintelligenz des Internetz zur Hilfe kommt (-;

Viele Grüße und schonmal vielen Dank,
Ron
Gast #7099575
Lesenswert?

Täusche ich mich da oder ist da was falsch:
MOVLW PORTA                         ;PORTA ins WREG laden
???????????
Um porta nach w zu laden schreibe ich üblicherweise den pseudobefehl 
"movfw".
"movlw" soll hingegen eine folgend angegebene Zahl in's w-reg. laden. 
Wenn dieser Zeile keine Fehlermeldung folgt wird vermutlich die Adresse 
von porta und nicht der Inhalt nach w geladen!
Schlage vor, das anhand des Datenblattes zu klären.

Das ist mir nur ins Auge gefallen - den code hab ich sonst nicht 
geprüft.
Gast #7099592
Lesenswert?

Hallo Hans,
da hast du natürlich völlig recht. Da muss natürlich stehen
MOVF PORTA, 0
Bringt aber leider nichts. Das Problem scheint nichts in der ISR zu 
sein, denn ich habe da auch schon sehr primitiven Code (also ohne Umwege 
LED anschalten) in die ISR geschrieben, da springt er einfach nicht hin.
Aber trotzdem schonmal danke, hat der Code schon einen Fehler weniger.
Grüße Ron
Gast #7099605
Lesenswert?

Hallo Ron,
vielleicht finde ich morgen zeit und schau nochmal.....
Nicht überprüfen kann ich -obwohl sehr wichtig- ob die ISR an der 
richtigen Adresse steht und ob. die Befehle an der Anfangsadr. d. 
Pgm-Speichers passend sind. Empfehlung: nochmals genau selbst prüfen.
PS.
MOVF PORTA, 0 bzw. MOVF PORTA, .0 (dec. null) ist sicher ok.
Gast #7099627
Lesenswert?

Hallo,
im MPLAB X eigenen Debugger bin ich schonmal alles durchgegangen. Kann 
man da eigentlich auch die Timer simulieren inkl. Interrupt simulieren?
Der Timer selbst ist sicher nicht das Problem, das konnte ich ja schon 
durch dauerhaftes Prüfen des TMR1IF-Bits prüfen. Das wird ja gesetzt, es 
wird nur offensichtlich kein Interrupt ausgelöst oder die ISR steht an 
der falschen Stelle. Habe ich hier eine Möglichkeit, die Position zu 
prüfen, außer auf die Linker Option -pInterrupt=0x04 zu vertrauen?
Grüße Ron
Gast #7099669
Lesenswert?

Hallo Hans,
danke für den ersten Tipp, das ist auf jeden Fall mal sehr interessant. 
Allerdings ist dort klar die ISR ab der Adresse 004 zu erkennen.
Deine zweite Frage verstehe ich nicht. Welcher Doppelpunkt? Doppelpunkt 
im Sinne des Zeichens ':' oder im Sinne dass ich zu einem Programmpunkt 
doppelt gehe? Ich darf doch von beliebig vielen Stellen an das selbe 
Label springen?
Grüße Ron
Gast #7099682
Lesenswert?

ich nehme an:
wenn dort z.B. steht "goto mittwoch"
dann sucht die IDE nach der zeichenfolge "mittwoch" und nicht nach der 
zeichenfolge "mittwoch:"
Ob das trotzdem funktioniert kann man z.B. aus dem programmspeicher 
sehen.
Gast #7099693
Lesenswert?

Der Doppelpunkt zeichnet die Zeichenfolge ja gerade erst als Label aus. 
Ohne Doppelpunkt gibt er dann auch nur aus, dass er den Befehl nicht 
kennt.
Das wäre auch hier nochmals auf Seite 274 nachzulesen:
https://ww1.microchip.com/downloads/en/devicedoc/50002053g.pdf
Solche Sprünge funktionieren an anderer Stelle im Programm hervorragend 
und selbst wenn sie in der ISR nicht gehen würden, so müsste ich doch 
wenigstens in der ISR rauskommen.
Danke und Grüße
Ron
Gast #7099723
Lesenswert?

Nachtrag:
.....allerdings verwende ich den compiler mpasm.
und das *.pdf bezieht sich auf den XC8 C compiler.
Ob und welche Unterschiede in der zuläsigen Bezeichnung der labels 
bestehen müsste man nachsehen - wenn man es genau wissen will oder muss.
Gast #7099759
Lesenswert?

Nachtrag:
Ich hab nachgelesen. Für den von mir verwendeten Assembler MPASM gelten 
folgende Regeln für die Schreibweise von labels.

"Labels should start in column 1. They may be followed by a colon (:), 
space, tab or the end of line. Labels must not begin with number."
Gast #7100128
Lesenswert?

Guten Morgen,
ja, das wird wohl dann an den kleinen aber feinen Unterschieden zwischen 
MPASM und pic-as liegen.
Ich habe mir nun nochmal die Mühe gemacht, im Simulator alle für die 
Interrupts wichtigen Register zu beobachten, und nun habe ich 
tatsächlich die Lösung gefunden!
INTCON = 11000000B            ;GIE und PIE an, das hat geklappt
PIE1 = 00000001B               ;T1IE an, hier war der Fehler
Denn das Register INTCON ist ja in allen Bänken erreichbar und so stand 
nach vor dem setzen von PIE1 kein BANKSEL. D.h. er hat an die selbe 
Stelle in der Bank 1 geschrieben, also in PIR1. Somit läuft der 
Interrupt durch Timer1 und auch durch Änderung an PORTA.
Zuletzt noch eine Verständnisfrage: Einige Register finden sich ja nur 
in einer Bank, während sich andere in mehreren oder sogar allen finden. 
Wie funktioniert das technisch? Gehen dann die "Leitungen" bei denen man 
mit Adresse 8B (INTCON in Bank 1) mit denen direkt logisch zusammen, wo 
man mit Adresse 0B (INTCON in Bank 0) zusammen?
Auf jeden Fall vielen Dank für die Hilfe, die dieses mal wirklich 
lobenswert konstruktiv und ohne die so oft zu lesenden Angeifereien 
funktioniert hat. So stelle ich mir ein Forum vor!
Danke und viele Grüße,
Ron
Gast #7100152
Lesenswert?

Ja, die Bankumschaltungen sind immer fehlerträchtig.
Im Datenblatt hab ich auch den Hinweis gefunden, dass in der ISR 
möglicherweise das banksel.-register geändert wird und nach dem 
Rücksprung aus der ISR geändert bleibt. -daher ist eventuell auch das zu 
sichern.
(Aber ist das Benksel-reg. nicht im status enthalten und dort 
gespeichert???)
Auch ist ein Code zur Sicherung von w u. status vorgeschlagen:

MOVWF W_TEMP ;Copy W to TEMP register
SWAPF STATUS,W ;Swap status to be saved into W
;Swaps are used because they do not affect the status bits
MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
:
:(ISR) ;Insert user code here
:
SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
;(sets bank to original state)
MOVWF STATUS ;Move W into STATUS register
SWAPF W_TEMP,F ;Swap W_TEMP
SWAPF W_TEMP,W ;Swap W_TEMP into W
Gast #7100329
Lesenswert?

Peter D. schrieb:
> Ein Interrupt oder eine aufgerufene Funktion kennen die gerade
> aktive
> Bank nicht. Sie müssen also die Bank sichern, ihre gewünschte Bank
> setzen und am Ende die Bank restoren.

Ist das nicht bei den moderneren Typen nicht mehr nötig, zB PIC16F1825, 
die haben doch einen Hardware-Stack
Gast #7100435
Lesenswert?

Hans B. schrieb:
> ich nehme an:
> wenn dort z.B. steht "goto mittwoch"
> dann sucht die IDE nach der zeichenfolge "mittwoch" und nicht nach der
> zeichenfolge "mittwoch:"

Ähem... naja, sowas hängt am konkreten Assembler. Normalerweise schreibt 
man ein Label
KarlheinzOtto:
wobei der Doppelpunkt anzeigt, daß das ein Label ist und bei einem 
Sprung oder Call muß man den Doppelpunkt weglassen und nur den 
eigentlichen Namen hinschreiben.

W.S.
Gast #7100463
Lesenswert?

OldMan schrieb:
> Ist das nicht bei den moderneren Typen nicht mehr nötig, zB PIC16F1825,
> die haben doch einen Hardware-Stack

Den Stack in Hardware hatten die PIC16 schon immer. Aber es hat wohl 
beim Übergang von den dreistelligen Nummern auf vierstellige Nummern im 
Namen auch einige Änderungen beim Interrupt gegeben.


Ron S schrieb:
> PSECT Interrupt, class=CODE, delta=2
>  ISR:
>     BANKSEL WREG_Temp
>     MOVWF WREG_Temp      ;WREG zwischenspeichern
>     BANKSEL STATUS
>     MOVF STATUS, 0      ;STATUS zwischenspeichern
>     MOVWF Status_Temp

Mir fällt da auf, daß dieses BANKSEL ja (bislang) kein Maschinenbefehl 
war, sondern ein Macro und das könnte das W Register benutzen.

Wenn man die Rett-Register im Bereich 70h..7fh anordnet, dann sind die 
(zumindest bei den Typen, die ich kenne) von allen Bänken erreichbar. Zu 
bedenken wäre auch, daß MOVF IrgendeinRegister immer auch die Flags 
ändert. Folglich sah das Registerretten etwa so aus:
1. W in W-Rettregister speichern (das ist in 70h..7fh)
2. Status nach W swappen (nicht laden)
3. W in Status-Rettregister speichern (das speichert auch die 
Bank-Einstellung, ist ebenfalls in 70h..7fh)
4. FSR retten und alles weitere

Ob das bei deinem PIC auch so ist oder bereits anders, hab ich jetzt 
nicht nachgelesen. Irgendwo hab ich bei den neueren Typen auch in 
Erinnerung, daß bei Interrupts das GIE gelöscht wird. Falls da was bei 
deinem PIC zutrifft und du keine Vorkehrungen getroffen hast, dann wäre 
der Interrupt nach dem allerersten Mal abgeschaltet.

W.S.



W.S.
Gast #7100513
Lesenswert?

Beim pic16f1688 muss man (noch) selbst für die Sicherung von STATUS und 
ARBEITSREGISTER sorgen.
Der Code dafür steht im Datenblatt. (SWAP für STATUS verwenden -wie von 
W.S. erwähnt)
Der GIE wird automatisch mit dem Einsprung in den Interrupt abgeschaltet 
und mit dem Endbefehl "RETFIE" wieder eingeschaltet.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren