Die Nutzung des Capture Eingangs

am Beispiel der PIC16F87x

zurück zu Input/Output , PIC-Grundlagen , PIC-Prozessoren , Elektronik , Homepage

Allgemeines
Initialisierung
Capturen
Beispiel


Allgemeines

Ich beziehe mich in diesem Text auf die PICs der Familie 16F87x. Natürlich kann der Capture-Mode mit allen PICs verwendet werden, die wenigstens ein CCP-Modul besitzen, aber bei anderen PICs als den 16F87x können Adressen einzelner Register auf anderen Adressen liegen oder es werden andere Pins verwendet. So verwendet der 16F628 z.B. anstelle von RC2 das Pin RB3 als Capture-Eingang.
Wer andere PIC-Typen einsetzen will, achte bitte auch die korrekten Adressen, Bänke und Pins.

Der Capture-Eingang eignet sich zum genauen Messen des Zeitpunktes, zu dem ein externes Ereignis eintritt. Dazu wird der Timer1 auf das Zählen des Prozessortaktes eingestellt. Ändert sich der Zustand am Eingang RC2, so wird in diesem Augenblick der Zählerstand des Timers1 in das Captureregister kopiert (ge-'capturet'). Als auslösendes Ereignis steht zur Verfügung:

Das zweite CCP-Modul reagiert auf Ereignisse am Eingang RC1.
Im Moment des Kopierens kann zusätzlich ein Interrupt ausgelöst werden.
.
Capturemode: Prinpipschaltbild
nach oben

Initialisierung
Das Capture-Modul Nr.1 wird mit dem Register CCP1CON (Adresse 17h) gesteuert, das Capture-Modul Nr.2 mit dem Register CCP2CON (Adresse 1Dh).

CCP1CON: CAPTURE/COMPARE/PWM-1-CONTROL (ADDRESS 17h):


bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
Name: - - CCPxX CCPxY CCPxM3 CCPxM2 CCPxM1
CCPxM0
Wert:
-
-
-
-
0
0
0 oder 1
0 oder 1

Für den Capture-Mode ist CCPxM3=0  und CCPxM2=1 zu setzen. Mit den Bits CCPxM1 und CCPxM0 wird ausgewählt, welches externe Ereignis das Capturen auslösen soll.
 

Mode
CCPxM1
CCPxM0
jede High-Low-Flanke
0
0
jede Low-High-Flanke
0
1
jede vierte Low-High-Flanke
1
0
jede sechzehnte Low-High-Flanke
1
1

Für eine Capture-Funktion bei jeder steigenden Flanke muss also CCP1CON mit 1 geladen werden:

; CAPTURE MODE mit CCP1 initialisieren
    CLRF     CCP1CON           ; CCP1-Modus aus
    BSF      CCP1CON,CCPxM0    ; CCP1-Modus in Capture Mode (L-H, 1:1)

Natürlich muss auch der Timer1 auf Zählen eingestellt werden. Außerdem sollte das zugehörige Pin als Eingang konfiguriert sein, was nach einem Reset ohnehin der Fall ist.

; RC2 auf Eingang stellen
    BSF      STATUS,RP0        ; Bank1
    BSF      TRISC, 2          ; RC2: input=1
    BCF      STATUS,RP0        ; Bank 0

Jedes Capture-Ereignis setzt das Interruptflag CCP1IF (CCP2IF) im Register PIR1. Soll dadurch ein Interrupt ausgelöst werden, so ist ist das zugehörige Enable-Bit zu CCP1IE (CCP1IE) im Register PIE1 setzen.  Das sollte erst erfolgen, nachdem die anderen Einstellungen abgeschlossen sind, und CCP1IF gelöscht wurde, da jedes Verändern von CCP1CON versehentlich CCP1IF setzen kann.
Zum Erlauben des Interrupts müssen noch das Haupt-Interrupt-Flag GIE und das Peripherie-Interrupt-Flag PEIE gesetzt sein.
 

nach oben


Capturen

Das Capturen kann man mit Polling (ständiges abfragen) oder durch einen Interrupt organisieren. Polling ist einfacher zu programmieren, verbraucht aber viel Rechenzeit.

Polling
Bei jedem Capturen wird das Bit CCP1IF (CCP2IF) im Register PIR1 (Adresse 0Ch) gesetzt. Dieses Bit kann man in einer Schleife abfragen. Ist das Bit gesetzt, liest man den gemessenen 16-Bit-Wert in zwei Hälften aus den Registern CCPR1H (CCPR2H) und CCPR1L (CCPR2L) aus. CCP1IF (CCP2IF)  muss per Software geläscht werden. Die folgende Routine pollt, und schreibt ein empfangenes Zeichen nach 'Zeichen':

Capture
    btfss   PIR1,CCP1IF      ; sind Daten da ?
    goto    Capture          ; nein, noch keine Daten da
    movfw   CCPR1H           ; High Teil
    movwf   CapHigh          ; in den Speicher nach 'CapHigh' schreiben
    movfw   CCPR1L           ; Low Teil
    movwf   CapLow           ; in den Speicher nach 'CapLow' schreiben
    bcf     PIR1,CCP1IF      ; Flag löschen

Interrupt
Das CCP-Modul kann beim Capturen einen Interrupt auslösen. Damit fordert er dazu auf, den gemessenen Wert abzuholen. Sollen Interrupts genutzt werden, müssen Interrupts generell erlaubt werden (GIE=1),  Peripherie-Interrupts erlaubt werden (PEIE=1) und im speziellen muss der Empfängerinterrupt freigeschaltet werden (CCP1IE=1 bzw. CCP2IE=1).

;Interrupts vorbereiten
    BSF     STATUS,RP0         ; Bank1
    BSF     PIE1,CCP1IE        ; Enable CCP1 interrupts
    BCF     STATUS,RP0         ; Bank 0
    clrf    PIR1               ; alle Interruptflags löschen
    clrf    PIR2
    BSF     INTCON,GIE         ; generell Interrupts erlauben
    BSF     INTCON,PEIE        ; Interrupts von Peripheriegeräten erlauben

Eine Interruptroutine die die gemessene Zeit in die Register 'CapHigh' und 'CapLoe' kopiert könnte wie folgt aussehen:

    org  4                   ; Interrupt beginnt immer bei Adresse 4
int
    movwf   w_temp           ; status retten
    swapf   STATUS,w
    movwf   status_temp

;Capture-Interrupt?
    btfss   PIR1,CCP1IF
    goto    intEnde          ; Interrupt kam von wo anders

    movfw   CCPR1H           ; High Teil
    movwf   CapHigh          ; in den Speicher nach 'CapHigh' schreiben
    movfw   CCPR1L           ; Low Teil
    movwf   CapLow           ; in den Speicher nach 'CapLow' schreiben
    bcf     PIR1,CCP1IF      ; Flag löschen

intEnde                      ; geretteten Status wieder zurückschreiben
    swapf   status_temp,w
    movwf   STATUS
    swapf   w_temp,f
    swapf   w_temp,w
    retfie

nach oben

Beispiel

Eines meiner Projekte ist ein Drehzahlmesser für Modellflugzeuge mit Zweiblattluftschraube, der sich natürlich auch an andere Anwendungsfälle anpassen lässt. Die Messung erfolgt mit dem Capture-Modul eines PIC16F628.

nach oben

zurück zu Input/Output , PIC-Grundlagen , PIC-Prozessoren , Elektronik , Homepage

Autor: sprut
erstellt: 03.07.2001