Ich hatte vor einiger Zeit schon einmal einen Beitrag gespostet, leider konnte mir nicht geholfen werden... jetzt steh ich vor dem selben Problem: Ich habe ein PIC16F886 und möchte über den Pin RB7 ein Interupt auslösen. Ich komme aber nicht ins die Routine. könnt ihr mir weiter helfen? So sieht meine ISR aus: org 0x04 InterruptServiceVector movwf W_save swapf STATUS,W bcf STATUS, RP0 movwf Status_save MOVFW PORTC XORLW B'00000001' MOVWF PORTC MOVFW PORTB Intende_ BCF INTCON,RBIF bcf INTCON, T0IF swapf Status_save, w movwf STATUS swapf W_save,f swapf W_save,w retfie Und das ist meine Konfiguration: #include <p16F886.inc> #define CONFIGURATION1 _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF #define CONFIGURATION2 _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF & _DEBUG_OFF __CONFIG _CONFIG1, CONFIGURATION1 & CONFIGURATION2 Init BANKSEL TRISB movlw b'10000000' movwf TRISB BANKSEL TRISC movlw b'00000000' movwf TRISC bsf STATUS, RP0 bsf OPTION_REG, INTEDG ; 0-1-Flanke an RB0 bcf STATUS, RP0 bsf INTCON, INTE bsf INTCON, GIE bsf IOCB,7 BANKSEL 0 Start_ GOTO Start_ END Vielen dank schonmal! Gruß Thomas
Hallo Thomas, ich kenn jetzt speziell den PIC16F886 Typ nicht - ABER wenn ich das noch richtig in Erinnerung habe, muß im INTCON auch noch das 'RBIE'-Bit gesetzt werden. (Bei den PIC16F76 Typen heißt das Bit auf jeden Fall so). Kann sein, daß es beim 886 anders heißt. Aber ohne das Enable-Bit kommt auch kein Interrupt. Gruß TK
Jetzt sieht der code so aus und funktiniert immernoch nicht:
#include <p16F886.inc>
#define CONFIGURATION1 _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF &
_MCLRE_ON & _CP_OFF
#define CONFIGURATION2 _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF &
_DEBUG_OFF
__CONFIG _CONFIG1, CONFIGURATION1 & CONFIGURATION2
org 0x00
GOTO Config
org 0x04
InterruptServiceVector
movwf W_save
swapf STATUS,W
bcf STATUS, RP0
movwf Status_save
MOVFW PORTC
XORLW B'00000001'
MOVWF PORTC
nop
MOVFW PORTB
MOVLW B'10000000'
MOVWF PORTB
nop
nop
Intende_
BCF INTCON,RBIF
bcf INTCON, T0IF
bcf INTCON,INTF
swapf Status_save, w
movwf STATUS
swapf W_save,f
swapf W_save,w
retfie
Config
BANKSEL TRISB
movlw b'10000000'
movwf TRISB
BANKSEL TRISC
movlw b'00000000'
movwf TRISC
bsf STATUS, RP0
bsf OPTION_REG,INTEDG ; 0-1-Flanke an RB0
bcf STATUS, RP0
bsf INTCON, INTE
bsf INTCON, GIE
bsf INTCON, RBIE
bsf IOCB,7
BANKSEL 0
Start_
GOTO Start_
END
Hat noch jemand eine Idee?
Wenn ich das richtig interpretiere, soll PORTC,0 mit jedem RB7 Int getoggelt werden. In dem letzten Code setzt Du innerhalb der ISR den PORTB,7 immer H. Da B7 jedoch Input ist, hat dieser Code eigentlich keine Wirkung. Wie wird denn extern der PORTB,7 angesteuert (oder soll nur eine Simulation durchgeführt werden)? Ansonsten seh ich jetzt erst mal kein weiteres Problem. Gruß TK
das mit dem PORTB,7 hab ich zum Test gemacht, weil im datenblatt etwas davon steht, dass der Port gelesen oder geschrieben werden muss um aus der ISR raus zu kommen. Ich steuer den eingang mit 5V direkt an ohne weitere anschaltung
Hallo, wenn du den Eingang ohne weitere Ansteuerung beschaltest, kann das zu Problemen führen, da kein definierter Zustand am Pin. Schalte die Pull-Up´s im OPTION-Register ein (RPPU = 0) und steuere PORTB,7 mit logisch 0 an.
Das mit dem PORT lesen um aus der ISR rauszukommen ist nur die halbe Wahrheit! Durch den MOVFW PORTB wird dieser Zustand bereits beendet. Ich denke mal an PORTC,0 hängt eine LED oder so. Durch das Schalten von 5V am PORTB,7 kann auch ein Prellvorgang entstehen (je nachdem, ob das mit einem Taster, oder mit einer Drahtbrücke oder so geschieht) Besser wäre innerhalb der ISR den PORTC,0 so auszugeben, dass dieser den gleichen Pegel wie B7 aufweist. Dann wäre nach einem Prellvorgang am Ende der Pegel von C0 identisch mit B7. Das kann man dann besser vergleichen, als nur einen reinen Toggeleffekt. Dabei prellt der C0 nämlich mit und am Ende kann C0 dann einen anderen Pegel aufweisen, als an B7. Und wie der Vorgänger schon geschrieben hat, reicht es nicht aus 5V an den Eingang zu legen. So bekommt man zwar immer einen schönen H-Pegel, aber der L Pegel stellt sich nicht automatisch ein, wenn man die 5V wieder weg nimmt. Daher sollte ein externer Pull-Down an B7 hängen oder aber die internen Pull-Ups aktiviert werden und dann nur mit externen 0V an B7 umgeschaltet werden. Gruß TK
Das sind gute Hinweise, ich werde das heute nachmittag mal Testen! - Pullups aktivieren und oV beschalten - Und statt C,0 zu Togglen besser c0= B7 ausgeben.
sooo,
tests abgeschlossen, leider nicht erfreulich... Ich habe meinen Code
jetzt so weit abgespeckt, dass nichts mehr stören kann und einen
Pull-Down Widerstand (100k) angeschlossen.
#include <p16F886.inc>
#define CONFIGURATION1 _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF
&_MCLRE_ON & _CP_OFF
#define CONFIGURATION2 _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
&_DEBUG_OFF
__CONFIG _CONFIG1, CONFIGURATION1 & CONFIGURATION2
W_save Equ 0x20
Status_save Equ 0x21
org 0x00
GOTO Configur
org 0x04
InterruptServiceVector
BSF PORTC,0 ;Test
BCF PORTC,0 ;Test
retfie
org 0xFA
Configur
BANKSEL TRISB
movlw b'10000000'
movwf TRISB
BANKSEL TRISC
movlw b'00000000'
movwf TRISC
BANKSEL ANSEL
CLRF ANSEL
BANKSEL 0
BANKSEL ANSELH
CLRF ANSELH
BANKSEL 0
BANKSEL OPTION_REG
bsf OPTION_REG,INTEDG
bcf OPTION_REG,7
BANKSEL 0
bsf INTCON, INTE
bsf INTCON, INTF
bsf INTCON, GIE
bsf INTCON, RBIE
MOVLW B'10000000'
MOVWF IOCB
CLRF PORTB
CLRF PORTC
Start_
GOTO Start_
END
Jetzt stellt sich mir die Frage, warum mein PortC,0 ständig an und aus
geschaltet wird? (siehe anhang)
Obwohl ich keinerlei änderungen am Pin RB7 habe.
Ist das eines sache der Konfiguration?
Wenn jemand die möglichkeit hat, das mal an eine PICKit2 oder ähnlichem
zu testen, würde mir das sehr weiter helfen!
Gruß
Thomas
Hallo Thomas, ich sehe gerade dass du in der INIT-Routine das RBIF-Flag setzt. Wieso denn das? Damit erklärt sich auch, warum du ständig einen Interrupt bekommst! In der ISR müssen am Ende alle aufgelaufenen Interrupts von "Hand" gelöscht werden. Das war in einem vorherigen Code ja bereits drin. Nachdem RETFIE abgearbeitet wird, kommt dann natürlich sofort wieder ein Interrupt - und zwar der INTF! Also nimm die alte ISR wieder - mit dem gesamten Overhead für W- und STATUS Register Rettung usw. Dann gehts auch. Ach so, noch was - In den ADCON und CCPCON Registern sollte man die Pins noch alle auf Digital schalten, wenn man nicht mit analogen Inputs arbeitet. Gruß TK
Das sind alles gute hinweise, jetzt sieht mein Code so aus... mit ein
paar kommentaren zum besser lesen.
In der Interruptrotine schalte ich PortC,0 kurz ein und wieder aus...
Mit den Osca kann ich dann messen ob der Pin schaltet.
#include <p16F886.inc>
#define CONFIGURATION1 _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF
&_MCLRE_ON & _CP_OFF
#define CONFIGURATION2 _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
&_DEBUG_OFF
__CONFIG _CONFIG1, CONFIGURATION1 & CONFIGURATION2
W_save Equ 0x20
Status_save Equ 0x21
org 0x00
GOTO Configur
org 0x04
InterruptServiceVector
movwf W_save
swapf STATUS,W
bcf STATUS, RP0
movwf Status_save
BSF PORTC,0
nop
nop
BCF PORTC,0
;PORTB Lesen/schreiben, damit ich
;RBIF Löschen kann
MOVFW PORTB
MOVWF PORTB
;Die Flaggen RBIF und INTF Löschen
BANKSEL INTCON
BCF INTCON,RBIF
BCF INTCON,INTF
BANKSEL 0
Intende_
swapf Status_save, w
movwf STATUS
swapf W_save,f
swapf W_save,w
retfie
org 0xE0
Configur
;RB7 - Input
;RB6:0 - Output
BANKSEL TRISB
movlw b'10000000'
movwf TRISB
BANKSEL 0
;RC7:0 Output
BANKSEL TRISC
movlw b'00000000'
movwf TRISC
BANKSEL 0
;alle Ports Digital
BANKSEL ANSEL
CLRF ANSEL
BANKSEL 0
BANKSEL ANSELH
CLRF ANSELH
BANKSEL 0
BANKSEL ADCON0
CLRF ADCON0
BANKSEL 0
BANKSEL ADCON1
CLRF ADCON1
BANKSEL 0
BANKSEL CCP1CON
CLRF CCP1CON
BANKSEL 0
BANKSEL CCP2CON
CLRF CCP2CON
BANKSEL 0
;PORTB Pull-up Disable - ist bei mir mit 100k nach
;Masse beschaltet Interupt bei steigender Flanke
BANKSEL OPTION_REG
bsf OPTION_REG,7
bsf OPTION_REG,INTEDG
BANKSEL 0
CLRF PORTB
CLRF PORTC
;Interrupt-on-Change Port - RB7
MOVLW B'10000000'
MOVWF IOCB
;Interrupt-on-Change Port Eingeschaltet
bsf INTCON,RBIE
;Externe Interrupt eingeschaltet
bsf INTCON,INTE
;Interruptflagge ausgeschaltet, wird beim Interrupt
;gesetzt und muss in der ISR zurück gesetzt werden
bcf INTCON,INTF
;WEAK Pull-Up deaktiviert
CLRF WPUB
;Globaler Interrupt aktiviert
bsf INTCON,GIE
Start_
GOTO Start_
END
Mit diesem Code springt das Programm garnicht erst in die ISR...
Das habe ich getestet, indem ich in der Routine INTF Und RBIF gesetzt
habe... sollte also das Programm in die ISR springen, würde ich in einer
endlosschleife hängen. Macht es aber nicht.
Wie im code beschrieben habe ich 100k gegen masse geschaltet und setze
den ausgang mit den 5V auf High.
Wenn ich manuel INTF in der initialisierung setze, springe ich in die
ISR
Theoretisch müsste doch mein eingang die Flagge INTF auslösen oder?
Muss ich noch irgendwas deaktivieren, oder in der Config aktivieren,
dass RB7 auch als interrupt erkannt wird?
IOCB liegt in Bank 1! Du bist beim Schreiben in das Register aber noch in Bank 0. Der IOC Interrupt benötigt nur das Bit RBIE und natürlich GIE. INTE ist nur für den RB0 Interrupt (INT) zuständig. Das kannst du also raus nehmen. Du solltest auch die Rettungsregister in den Bereich 0x70 - 0x7F legen. Du weist nicht in welcher Bank sich der µC befindet wenn er in die ISR springt und es kann sein, dass du deine Register in die falsche Bank sicherst. 0x70 - 0x7F liegen im Access-Ram und haben von allen Bänken aus den gleichen Inhalt. Ich würde es so probieren: Init: - PortB auf digital schalten (ANSELH) - PortB löschen - TrisB setzen - IOCB setzen - eventuell WPUB setzen (Pull-Ups) - im INTCON RBIE und GIE einschalten ISR: - Register retten (nach sprut) - Routine abarbeiten - RBIF löschen - Register zurück schreiben - zurück springen Hauptprogramm: - erst mal nur die Endlosschleife Sven Ach ja: WPUB liegt auch in Bank1
Sven Stefan.... du bist es!! Vielen Danke! Jetzt funktioniert es! Hab IOCB in Bank 1 gesetzt und die Rettungsregister auf x71 und x72 geleget! Da freu ich mich doch. Gruß Thomas
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.