Forum: Mikrocontroller und Digitale Elektronik Interupt on Change PIC


von Tom (Gast)


Lesenswert?

Wie kann ich bei einem PIC16F886 einen Interrupt on change an PortB,7 
auslösen?
Ich komm einfachn nicht in die Interrupt routine rein :(

Bitte um kurze hilfestellung, welche Bits ich setzen bzw, löschen muss.

Vielen Danke!

von tastendrücker (Gast)


Lesenswert?

Wie wäre es mit ein bisschen Code? Sonst raten sich alle einen Wolf...

von Tom (Gast)


Lesenswert?

org  0x0
       GOTO Init
org     0x04

InterruptServiceVector
        movwf   W_save
        swapf   STATUS,W
        bcf     STATUS, RP0
        movwf   Status_save

    BTFSS  PORTC,3
    BSF    PORTC,3
    BTFSC  PORTC,3
    BCF    PORTC,3

Intende_

    BCF    INTCON,RBIF
     bcf     INTCON, T0IF
    swapf   Status_save, w
        movwf   STATUS
        swapf   W_save,f
        swapf   W_save,w

        retfie



Init
  BANKSEL    1
  movlw    b'10000000'
  movwf    TRISB

        bsf     INTCON, GIE
        bsf  IOCB,7
  BANKSEL    0
Start_

  GOTO  Start_

von tastendrücker (Gast)


Lesenswert?

Du musst in deiner INIT-Routine den PortB auf Digital-I/O schalten (ist 
nach PowerON auf Analog IN)

 BANKSEL 3
 MOVLW   0
 MOVWF   ANSELH
 BANKSEL 0

von holger (Gast)


Lesenswert?

RBIE in INTCON zu setzen dürfte auch nicht schaden.

von Tom (Gast)


Lesenswert?

auch nachdem ich
 BANKSEL    1
  movlw    b'00000000'
  movwf    TRISC
für den ausgabe Pin eingefügt habe gehts leider nicht.

noch eine Idee?

von tastendrücker (Gast)


Lesenswert?

> RBIE in INTCON zu setzen dürfte auch nicht schaden.

stimmt
(waren die nicht früher auf '1' nach PON?...)

von Tom (Gast)


Lesenswert?

RBIE  hat leider auch nichts genutzt

von tastendrücker (Gast)


Lesenswert?

>auch nachdem ich
> BANKSEL    1
>  movlw    b'00000000'
>  movwf    TRISC
>für den ausgabe Pin eingefügt habe gehts leider nicht.

He? Was soll'n das?  Ich denke du hast ein Problem mit IntOnChange an 
PORTB? Was hat denn die Richtung von PORTC damit zu tun?

von Tom (Gast)


Lesenswert?

naja, mit dem PortC,3 überprüfe ich, ob ich auch in den Interupt 
gesprungen bin.

von holger (Gast)


Lesenswert?

@tastendrücker
>(waren die nicht früher auf '1' nach PON?...)

The interrupt-on-change feature is
disabled on a Power-on Reset.


Wüsste nicht das es jemals anders war ;)

von tastendrücker (Gast)


Lesenswert?

Ach so ja, die Ausgabe...

Passiert überhaupt was? Schwingt der Quarz oder nimmst du den internen 
Oszi? In deiner Start-goto-Start würde ich mal ein PORTC-Pin toggeln, um 
zu sehen, ob der PIC überhaupt läuft

von Tom (Gast)


Lesenswert?

PIC läuft
aber der interrupt nicht.
Wo kann ich denn einstellen, ob der Pin auf Lo->Hi oder Hi-Lo reagiert?
oder reagiert der auf beide flanken?

von tastendrücker (Gast)


Lesenswert?

Reagiert auf beide Flanken. Und: Das Interrupt-Flag musst du in der ISR 
wieder löschen, sonnst wird kein neuer Interrupt ausgelöst.

von holger (Gast)


Lesenswert?

>PIC läuft
>aber der interrupt nicht.

Hast du den Tip von tastendrücker auch programmiert ?

>Wo kann ich denn einstellen, ob der Pin auf Lo->Hi oder Hi-Lo reagiert?
>oder reagiert der auf beide flanken?

Interrupt On Change reagiert auf beide Flanken. Bei jeder
Änderung (Change) eben. Wenn du eine bestimmte Flanke möchtest
musst du das per Software lösen.

von Tom (Gast)


Lesenswert?

ja, ich habe alles so gemacht wie er vorgeschlagen hat.
Ist es vielleicht noch wichtig zu erwähnen, dass ich ein PicKit2 
verwende?

von tastendrücker (Gast)


Lesenswert?

Dass heisst: Ein Pin toggelt im Betrieb vor sich hin - aber der 
Interrupt löst nicht aus...

Poste doch noch mal den aktuellen Code

Wie wird denn der Pin angesteuert?

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Inwieweit banksel mit einer Konstante funktioniert kann ich nicht sagen. 
Die Syntax lautet jedenfalls "banksel label" und wird von mir nur so 
verwendet. Also z.Bsp. so:

    label  equ  0x20
    banksel label

Ansonsten solltest du RBIE noch setzen, sonst werden die IOC-Interrupts 
nicht eingeschaltet. Da RB7 nicht analog benutzt wird, dürfte das 
Umstellen auf digital keine Rolle spielen.

Weiterhin funktioniert deine LED-Toggle-Routine so nicht (hab ich auch 
Anfangs so machen wollen, geht aber nicht)

    BTFSS  PORTC,3
    BSF    PORTC,3
    BTFSC  PORTC,3
    BCF    PORTC,3

Warum? Wenn RC3 Low hat, prüfst du dies auf Zeile 1. Da nicht gesetzt, 
wird der Port auf Zeile 2 gesetzt. Nun prüfst du auf Zeile 3 ob Port 
gesetzt. Ist er nun (wegen Zeile 2) also wird er auf Zeile 4 
zurückgesetzt. Deine LED wird nie leuchten. Ich mach das immer so

   movlw  b'00001000'
   xorwf  PORTC,3      ;LED1 toggeln

Probier es ruhig mal.

Sven

von tastendrücker (Gast)


Lesenswert?

>Weiterhin funktioniert deine LED-Toggle-Routine so nicht (hab ich auch
>Anfangs so machen wollen, geht aber nicht)

>    BTFSS  PORTC,3
>    BSF    PORTC,3
>    BTFSC  PORTC,3
>    BCF    PORTC,3

Oops, is' mir gaanich aufgefallen...

>   movlw  b'00001000'
>   xorwf  PORTC,3      ;LED1 toggeln

muss aber sein:

   movlw  b'00001000'
   xorwf  PORTC,1      ;LED1 toggeln
                ^

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Dann musst du aber auch das richtige Bit xor'en

  movlw  b'00000010'
                 ^

von tastendrücker (Gast)


Lesenswert?

@Sven Stefan

nein, es gibt nur

   xorwf  PORTC,0      ; -> Ergebnis in WREG
   xorwf  PORTC,1      ; -> Ergebnis in PORTC

daher:

   movlw  b'00000001'
   xorwf  PORTC,1      ; RC0 toggeln

   movlw  b'00000010'
   xorwf  PORTC,1      ; RC1 toggeln

   movlw  b'00000100'
   xorwf  PORTC,1      ; RC2 toggeln

   movlw  b'00001000'
   xorwf  PORTC,1      ; RC3 toggeln

   :

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Ooops, was hab ich denn da mal in meinem Programm geschrieben (ich hab 
das nur aus einem meiner Programme rauskopiert gehabt)? Ich schreib doch 
eigentlich immer

  xorwf   PORTC,f   (und nicht PORTC,1)

Wo ich mir doch nie merken kann was die 1 bzw. 0 hinter dem Komma 
bedeutet ;-)

Gruß
Sven

von tastendrücker (Gast)


Lesenswert?

Ja, man sollte wenn möglich die Symbole verwenden

 w = 0 = WREG  (Ergebnis der Operation wird ins WREG gespeichert)
 f = 1 = file  (Ergebnis der Operation wird ins file gespeichert)

von Tom (Gast)


Lesenswert?

Vielen dank für eure Ausführungen, aber...
Geht immernoch nicht, bin ich zu doof?
Hoffentlich sagt ihr jetzt ja und erklärt mir was ich falsch mache.
Hier mein Code

#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    0x26
Status_save  EQU    0x27


  org   0x00
  GOTO  Configuration

  org     0x04

Interrupt
  movwf   W_save
  swapf   STATUS,W
  bcf     STATUS, RP0
  movwf   Status_save

  movlw  b'00000100'
  xorwf  PORTC,3      ;LED3 toggeln

   BCF    INTCON,RBIF
      bcf     INTCON, T0IF

  swapf   Status_save, w
        movwf   STATUS
        swapf   W_save,f
        swapf   W_save,w
  BCF  PORTB,3
        retfie

Configuration
  clrf    PORTC
  BANKSEL    TRISC
  movfw    TRISC
  andlw    b'00000000'
  movwf    TRISC
  BANKSEL    0

  clrf    PORTB
   BANKSEL    TRISB
  movfw    TRISB
  iorlw    b'11111111'
  movwf    TRISB
  BANKSEL    0

  BANKSEL ANSEL ;
  CLRF    ANSEL
  BANKSEL ANSELH ;
  CLRF    ANSELH
  BANKSEL    0

  BSF     INTCON,RBIE
        bsf     IOCB,7
        bcf     OPTION_REG,7
   bsf     INTCON, GIE

Start_
  movlw   b'0001000'
  xorwf   PORTC,3      ;LED1 toggeln
  GOTO  Start_

     end



Mein signal das ich anlege ist... +Versorgungsspannung und GND ohne 
beschaltung.

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Arbeitest du auch manchmal mit dem Simulator? Und liest du auch die 
Fehlermeldungen? Dann hättest du gesehen was falsch läuft...

1. Routine Interrupt:

    movlw  b'00000100'
    xorwf  PORTC,3      ;LED3 toggeln

   Das hatten wir doch schon hier besprochen. Da hatte ich einen Fehler 
geschrieben. Hinter xorwf PORTC,3 kann keine 3 stehen nur ein f oder w. 
Mach da also ein f draus. In dem Befehl davor (movlw b'00000100' musst 
du die 1 um eine Stelle nach links versetzen, wenn du deine LED an 
PORTC,3 angeschlossen hast.

2. Falsche Register Bank (die Zeilen vor Marke Start)

  BANKSEL    0

  BSF     INTCON,RBIE
  bsf     IOCB,7
  bcf     OPTION_REG,7
  bsf     INTCON, GIE

INTCON liegt in Bank 0 -> richtig
IOCB und OPTION_REG liegt in Bank 1 -> musst du vorher umschalten!

So, und wenn das auch nicht geht, weiß ich nicht mehr weiter.

Schönen Abend noch (und grübel ruhig selbst mal ein wenig)

Sven

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Ach ja, deine LED toggelt nun in der Startschleife mit einer Frequenz 
von ein paar Megaherz. Du wirst das also nicht bemerken. Die LED wird 
immer leuchten.

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Und das bcf PORTC,3 vor retfie ist zuviel nimm es raus. Dadurch löschst 
du die LED gleich wieder, nachdem du sie eingeschaltet hast.

So nun hab ich bei der Simulation den Fehler, dass das Programm nicht 
mehr aus der Interruptroutine herauskommt. Nach einem Blich ins 
Datenblatt:

This interrupt can wake the device from Sleep. The user,
in the Interrupt Service Routine, clears the interrupt by:

a) Any read or write of PORTB. This will end the
mismatch condition.

b) Clear the flag bit RBIF.

Du musst also vor dem löschen des RBIF-Bits noch den PortB lesen. Sonst 
wird das RBIF Bit nicht zurückgesetzt und die ISR kann nicht beendet 
werden.

Also bei mir läuft die Simulation. Nun du...

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.