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.