Postat: 13 september 2008, 16:01:57
OK. Med allt jag sist och slutligen behövde i min ISR fick jag problem att hinna med. Inet ens med 8MHz klocka. Försökte då sätta PortA för Interrupt on change och läsa pulserna med bit 0 och riktning i bit 1. Nackdelen är då att jag får dubbla antalet pulser (en puls innebär två nivåförändringar). Testade då:
Nackdelen är då att det inte alls är säkert att portA har samma värde då jag läser den som då den triggade interrupten...
Men, eg vore det väl enklare att köra in pulserna på RA2/INT som ju triggar på valbar flank. Testade det och då gär det mycket bättre. Klarar av att räkna upp till 15-20kHz. Testade mot en HP pulsräknare.
En intressant sak upptäckte jag dock: Om jag drar upp frekvensen mycket över detta så tappar jag pulser, men, precis i området före så kommer koden att räkna flera pulser än räknaren. Kan någon förklara detta?
Bettendet är även symmetriskt, dvs både vid upp och nedräkning.
Kod: Markera allt
BTFSS INTCON, RABIF ; Was the cause PortAB interrupt?
GOTO other_int ; no, check ther interrupt
MOVF PORTA, W ; Port A change caused interrupt.Read PortA into flag register
movwf flags
btfss flags,0 ; Counter input high?
goto cnt_end
Men, eg vore det väl enklare att köra in pulserna på RA2/INT som ju triggar på valbar flank. Testade det och då gär det mycket bättre. Klarar av att räkna upp till 15-20kHz. Testade mot en HP pulsräknare.
En intressant sak upptäckte jag dock: Om jag drar upp frekvensen mycket över detta så tappar jag pulser, men, precis i området före så kommer koden att räkna flera pulser än räknaren. Kan någon förklara detta?
Bettendet är även symmetriskt, dvs både vid upp och nedräkning.
Kod: Markera allt
INTERRUPT
;
; Arrive here on any interrupt - first save the world...
;
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
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
btfss intcon, intf ; Was the cause an external interrupt? (RA2)
goto check_rabif ; no, check if cause is PortAB interrupt on change?
; Yes, pulse arrived on RA2
banksel cntr
movlw cntr ; Put counter in W
btfss flags,1 ; Bit 1 of flags indicate up/down
goto cnt_up
call dec32z ; Decrement
goto cnt_end
cnt_up
;
; Code that skips every nth pulse to account for battery efficiency
;
banksel effcounter
movf effcounter,F ; If zero, then skip efficiency adjustment
btfss status,z
goto cnt_up2
decfsz effcounter,1 ; Decrement efficiency counter
goto cnt_up2 ; and if not zero, then we increment
; if we have counted down, then we prime the register again
; net result is that every nth pulse is skipped. E = 1 - 1/n
; Ie 2 =50%, 3 = 66%, 4 = 75%, 5 = 80%, 6 = 83%, 7 = 86%, 8 = 88%, 9 = 89%, 10 = 90%
; 255 = 99.6%
movf effcounter_init,0
movwf effcounter
goto cnt_end
cnt_up2;
banksel cntr
call inc32z ; Increment
cnt_end
bcf intcon,intf ; Clear external interrupt flag
goto exit_interrupt
;
check_rabif
BTFSS INTCON, RABIF ; Was the cause PortAB interrupt?
GOTO other_int ; no, check ther interrupt
MOVF PORTA, W ; Port A change caused interrupt.Read PortA into flag register
movwf flags
BCF INTCON, RABIF ; Clear the RAB interrupt flag.
goto exit_interrupt
;
; 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
banksel dspcounter ; Check our loop counter if it is time to go and update stuff
decfsz dspcounter ; Time to go?
goto other_int1 ; No, not yet
bsf prtflag,1 ; Yes, set flag to indicate to main loop that we need an update
movlw DISPDELAY ; Prime the display delay counter
movwf dspcounter
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
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