Forum: Mikrocontroller und Digitale Elektronik PIC Capturing (16F877) zur Pulsbreitenmessung, aber wie genau?


von Hagen S. (Firma: SCT) (hagen68)


Lesenswert?

Hallo!

Ich versuche eine Implusbreite mittels der Capture-Funktion eines 16F877 
zu realisieren. ´Sprut's Seite hat dabei schon prima geholfen, es fehlt 
mir aber irgendwie noch ein wenig Information zum grundsätzlichen 
Ablauf.

Die Init sieht etwa so aus:

  banksel CCP1CON
  clrf   CCP1CON
  bcf   CCP1CON,CCP1M0
  bcf   CCP1CON,CCP1M1
  bcf   CCP1CON,CCP1M3
  bsf   CCP1CON,CCP1M2

    banksel PIE1
    BSF     PIE1,CCP1IE

    banksel PIR1
    clrf    PIR1
    clrf    PIR2
    BSF     INTCON,GIE
    BSF     INTCON,PEIE

Die Interrupts kommen korrekt an der erwarteten Flanke, ich habe einen 
Logic-Analyzer sowohl am Eingang (zu messende Größe) als auch an meinem 
Zestausgang.

De3r Int sieht so aus:

  movwf   w_temp              ; save off current W register contents
  movf  STATUS,w            ; move status register into W register
  movwf  status_temp         ; save off contents of STATUS register
  movf  PCLATH,w        ; move pclath register into w register
  movwf  pclath_temp        ; save off contents of PCLATH register

  banksel PORTC

  bsf PORTC,0 ; Zur Ereignisanzeige-ASnfang im Analyzer auf 1 setzen

;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

  clrf TMR1L
  clrf TMR1H
  clrf CCPR1H
  clrf CCPR1L

    bcf     PIR1,CCP1IF        ; Flag löschen

intEnde                        ; geretteten Status wieder 
zurückschreiben

  movf CapHigh        ; Entscheiddung 0 oder 1
  sublw .120  ; Schwellwert
  btfss STATUS,C        ; Übergehe next wenn Übertrag=1
  goto SetBit
;
; Bit 7 Soll die Definition von 0 oder 1 anzeigen, funktioniert aber 
nicht richtig!!
;
  clrw PreamCount        ; keine Preambel!
  bcf   PORTC,7        ; eine Null!!
  goto   SetEnd
SetBit
  bsf   PORTC,7        ; eine Eins!!
  incf PreamCount,1

  movf  PreamCount
  subwf  D'14'

  btfss STATUS,Z
  goto SetEnd

  clrf PreamCount
  bsf PORTC,6          ; Preambel-Marker
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  bcf PORTC,6

SetEnd
  bcf   PORTC,0  ; Zur Ereignisanzeige-Ende im Analyzer auf 0 setzen

  movf  pclath_temp,w      ; retrieve copy of PCLATH register
  movwf  PCLATH          ; restore pre-isr PCLATH register contents
  movf    status_temp,w       ; retrieve copy of STATUS register
  movwf  STATUS              ; restore pre-isr STATUS register contents
  swapf   w_temp,f
  swapf   w_temp,w            ; restore pre-isr W register contents
  retfie                     ; return from interrupt


Sinn und Zweck soll sein, daß alle Abstände zwischen den 
Int-Ereignissen, die kleiner/gleich 120 Mikrosekunden als 1-Wert 
darzustellen, alle Zeiten zwischen zwei Interrupts die größer alls 120 
Mikrosekunden sind sollen eine 0 darstellen.

Der Capture-Mechanismus kopiert laut Sprut (und auch laut der PIC-Doku) 
die Werte von Timer0 in temporäre Variablen. Was ich irgendwie nicht so 
richtig verstanden habe: muß ich den Timer dann selbst zurücksetzen?

Gibt bes vielleicht einen eleganteren Weg, die Pulsbreiten per 
Schwellwert zu bestimmen?

Ich bin noch relativer PIC-Neuling, habe früher sehr viel mit 
x86-Assembler programmiert und denke leider noch immer nicht wirklich in 
RISC-Instruktionen.... Aber Übung soll ja den Meister machen.

mfg
Hagen Schlömer

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.