Forum: Mikrocontroller und Digitale Elektronik Probleme mit Interrupts bei PIC16F688


von Ron S (Gast)


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

von Timer 1 (Gast)


Lesenswert?

Ron S schrieb:
> GIE
> und PEIE sind gesetzt.

ist TMR1IE auch gesetzt? Ansonsten wird kein IRQ ausgelöst.

von Ron S (Gast)


Lesenswert?

Hallo,
ja das hatte ich vergessen zu erwähnen, ist auch gesetzt.
Grüße

von Hans B. (Gast)


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.

von Ron S (Gast)


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

von Hans B. (Gast)


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.

von Ein Ratschlag (Gast)


Lesenswert?

Am einfachsten das Programm im Emulator oder In-Circuit-Debugger laufen 
lassen und dann absolut alle Register überprüfen, die das Datenblatt im 
Kapitel TMR1 erwähnt.

von Ron S (Gast)


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

von Hans B. (Gast)


Angehängte Dateien:

Lesenswert?

programmspeicher kann man einsehen.
bei mir kommt man so zur anzeige -siehe bild.

(vorher muss man glaub ich auf "clean and build" klicken)

von Hans B. (Gast)


Lesenswert?

nochwas ist mir aufgefallen:
mehrmals kommt vor: "goto EndeInterrupt"
Aber der Label lautet dann "EndeInterrupt:"
Was macht die IDE aus dem dann plötzlich vorhandenem Doppelpunkt?

von Ron S (Gast)


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

von Hans B. (Gast)


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.

von Ron S (Gast)


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

von Hans B. (Gast)


Lesenswert?

OK - ich verwende niemals den Doppelpunkt in einem Label.
Wenn Beides funktioniert is es ja gut so.
-werde das nachlesen....

von Hans B. (Gast)


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.

von Hans B. (Gast)


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."

von Ron S (Gast)


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

von Hans B. (Gast)


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

von Peter D. (peda)


Lesenswert?

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.

von OldMan (Gast)


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

von Peter D. (peda)


Lesenswert?

OldMan schrieb:
> Ist das nicht bei den moderneren Typen nicht mehr nötig, zB PIC16F1825,

Die sichern das BSR im Interrupt, aber in einem Call muß man das immer 
noch selber machen.

von W.S. (Gast)


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.

von W.S. (Gast)


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.

von Hans B. (Gast)


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.

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
Noch kein Account? Hier anmelden.