Frekvensräkning med CCP?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Frekvensräkning med CCP?

Inlägg av AndersG »

Måste bara ventilera litet här. Kanske det finns ett enklare sätt? Synpunkter mottages med tacksamhet

16F690 med intern RC osc på 8MHz. Timer1 matas av en extern 16MHz kristalloscilator. CCP är satt att göra en "capture" på varje positiv flank. Målet är helt enkelt att räkna varvtal, 10..20 000 1/min, 4 pulser/varv från en hallgivare.

Eftersom 16 bitar kan vara litet snött så hat T1 en overflowräknare i mjukvara för att klara riktigt låga varvtal.

ISR:

Kod: Markera allt

;**********************************************************************************************************
; ISR
;**********************************************************************************************************
INTERRUPT
; Keep the actual ISR as short as possible.
;
; Arrive here on any interrupt - first save the world...
; 
	movwf   w_temp 			; save off current W register contents
	swapf	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
	movf    FSR,w          	; move fsr register into W register
	movwf   fsr_temp       	; save off contents of PCLATH register

; Actual isr code, determine cause of interrupt. Most likely first
;
; This is the handler for the CCP interrupts
;
	banksel	PIR1
	btfss   PIR1,CCP1IF     ; CCP fired?
	goto	other_int		; No, check next

	BCF     T1CON,TMR1ON    ; Stop timer
	clrf	tmr1l			; Clear timer
	clrf	tmr1h
	BSF     T1CON,TMR1ON    ; Start timer


	movf    ccpr1l,w		; 
	movwf   count	
	movf    ccpr1h,w		; 
	movwf   count+1
	movf    t1of,w			; 
	movwf   count+2
	movf    t1of+1,w		; 
	movwf   count+3

	clrf	t1of			; Clear  overflow
	clrf	t1of+1	

	BCF 	PIR1,CCP1IF 	; Clear flag and continue.
;
; This is the handler for other interrupts, ie timer1
;
other_int
	;banksel	PIR1
	btfss   PIR1,TMR1IF     ; If Timer 1 overflowed and caused the interrupt, handle it.
	goto	other_int1		; No timer overflow

	incfsz  t1of,F		; Yes, increment overflow
	goto	other_int1			
	incf	t1of+1

other_int1

	banksel	PIR1
	BCF 	PIR1,TMR1IF 	; Clear flag and continue.
;
; Catch-all for interrupt exit. Restore the world as we know it.
;
exit_interrupt
	movf    fsr_temp,w		; retrieve copy of FSR register
	movwf   fsr				; restore pre-isr FSR register contents
	movf    pclath_temp,w	; retrieve copy of PCLATH register
	movwf   PCLATH			; restore pre-isr PCLATH register contents
	swapf   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
;**********************************************************************************************************
; END ISR
;**********************************************************************************************************
Initialisering

Kod: Markera allt

; ***********************************************************************************
; START OF CODE to initialize Timer 1

; Set up Timer 1 to count every 0.5us (16MHz/8)
; This is used by the CCP to measure pulse length
;
	banksel	tmr1l
	CLRF    TMR1L            	; Clear Timer1 register
	CLRF	TMR1H

	banksel	intcon
	bsf     INTCON,PEIE     	; Enable peripheral interrupts
	banksel	pie1
	CLRF    PIE1            	; Mask all peripheral interrupts except
	bsf     PIE1,TMR1IE     	; the timer 1 interrupts.

	banksel	pir1
	CLRF    PIR1            	; Clear peripheral interrupts Flags

	movlw   B'00110110'     	; Set  Prescale = 8, ext clock

	movwf   T1CON
	BSF     T1CON,TMR1ON    	; Timer1 starts to increment
;***********************************************************************************
;END OF CODE to initialize CCP
;***********************************************************************************

; Set up CCP module
	banksel CCP1CON
	movlw   B'00000101'     	; Set up CCP as capture, every rising edge
	movwf	CCP1CON

	banksel	pie1
	bsf     PIE1,CCP1IE     	; Enable CCP1 interrupts.

	banksel	intcon
    bsf		INTCON, GIE          ; enable interrupts
Då jag testar får jag ett ganska konstant "fel" om 20 pulser, dvs 10us, vilket borde stämma ganska bra då "stoppuret" i MPLAB ger 7us från interrupt, till att T1 är nollad och börjar räkna igen. Interruptlatensen är enligt manualen 3-4 tcy eller ca 2us.

Övrig kod skall inte göra så mycket. Visa på display, bryta ifall man övervarvar, samt kunna läsas från en PC bis RS-485.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Frekvensräkning med CCP?

Inlägg av bearing »

Varför stannas och nollställs timern i interruptet?

En av de fina sakerna med CCP-enheten är att den kan ställas in att nollställa timern automatisk när pinnen påverkats, just för att slippa jitter-problem. Nuvarande lösning gör att, ifall t.ex. "other_interrupt" håller på just när pinnen påverkas, kommer nollställningen fördröjas ytterligare.

Vad är anledningen till att bara timern, och inte hela processorn körs från kristalloscillatorn?
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: Frekvensräkning med CCP?

Inlägg av AndersG »

Jo, jag vet, men som jag förstår det så fungerar "SPECIAL EVENT TRIGGER" bara i Compare mode, inte för capture. Eller har jag fel?

Orsaken att jag kör processorn på det interna var att jag inte fick det att fungera med samma externa klocka för MPU och Timer 1
11.1.2 TIMER1 MODE SELECTION
Timer1 must be running in Timer mode or Synchronized
Counter mode for the CCP module to use the capture
feature. In Asynchronous Counter mode, the capture
operation may not work.
Således måste jag köra Timer 1 synkroniserad? Sedan förstod jag det så att pinnen är antingen T1CKI eller CLKIN?
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Frekvensräkning med CCP?

Inlägg av bearing »

Du har rätt, jag blandade ihop med Compare mode. Minns att jag löste problemet genom att låta timern snurra ohindrat, och beräkna perioden på signalen genom att subtrahera aktuellt Capture-värde från förra Capture-värdet.

Ska jag tolka det som att du valt extern klocka till Timer1, och inte Fosc/4, för att få 4x högre upplösning?
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: Frekvensräkning med CCP?

Inlägg av AndersG »

Ska jag tolka det som att du valt extern klocka till Timer1, och inte Fosc/4, för att få 4x högre upplösning?
Ja, plus att:
Timer1 must be running in Timer mode or Synchronized
Counter mode
Kan jag köra klockan synkad på annat sätt?
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Frekvensräkning med CCP?

Inlägg av Icecap »

Jag tycker att du har vald fel mätsätt!

Helt rätt att använda Capture men när du måste lägga extern frekvens till för att få hastigheten upp är det något fel!

Att expandera mätningens omfång till att kunde klara låga frekvenser är alldeles OK, faktisk nödvändigt men VAD mäter du? Måste du få ut ett mätvärde för varje puls?

Då det ju tydligen har med en motor att göra och den ska kommunicera medelst RS485 duger det alltså alldeles fint att mäta varannan motorvarv, alltså dela inkommande pulser med 8. Om vi antar en tomgångs-RPM på 600 blir det 20ms mellan varje mätning på lägsta varvet och jag tror inte att en övervarvslampa reagerar så pass snabbt ändå så 20ms hit eller dit lär knappast ha betydelse.

Så jag hade delat ner pulsernas antal en del och räknat på hur långt ner jag kunde dela utan att förlora "kontakten" och den externa oscillatorn hade jag då drivit hela PIC'en på för att få noggrannhet om det ska vara så exakt att den interna oscillator inte duger.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Frekvensräkning med CCP?

Inlägg av bearing »

Jag förstår inte riktigt vad du frågar här Anders. För att Capture ska fungera tillförlitligt behöver du ställa in Timer1 att gå i antingen "Timer mode" eller "Synchronized Counter mode".
"Timer mode" = Timer 1 klockas av Fosc/4
"Synchronized Counter mode" = Timer 1 klockas av extern klocka på OSC1/T1CKI-pinnen, och går sedan genom en synkroniseringskrets. Se fig. 6-1.

Eftersom att den externa klockan är mer stabil, samt snabbare, än interna klockan ser jag det som osäkert vad resultatet blir av synkroniseringen.
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: Frekvensräkning med CCP?

Inlägg av AndersG »

OK. Således borde jag testa att mata in min externa klocka och i stället klocka timern med Fosc/4.

Det är frågan om loggning av motorvarvtal till en bromsbänk så jag behöver säkert inte få ett nytt mätvärde varje varv. Om jag antar att maxvarv är 15.000 och får fyra pulser per varv (fyra hål i startkransen) så får jag 1000Hz, vill jag ha 1/100 upplösning/repeterbarhet så bör väl timerns klocka vara >=100kHz eller hur? Dividerar jag varvtalspulserna med 2 så halveras detta.
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Frekvensräkning med CCP?

Inlägg av Icecap »

Dela du tryggt med 8, då får du varannan varv och det skulle nog räcka långt men behöver du varje varv är det bara att dela med 4.

Motorn lär dock knappast varva upp så pass snabbt att det inte räcker med att mäta varannan varv.
Skriv svar