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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.