Hi guys, I've spent 2 night trying to suss this and am still perplexed. I've a PIC 16F882 with an external 20MHz crystal giving 5Mips. I've confirmed this with the RB0 output. I want to create an interrupt every ~20us, so I thought 100x 200ns instruction period == 20us. However when I set TMR0 = 255-100, I get an interrupt period of 34us. If I set TMR0=255-200, I get a period of 54us so the marginal change is correct ie. 20us per 100 change in TMR0 seed. But where's the fixed 14us overhead coming from? I expected to lose a few instructions, but 14us is 70 instructions! I've tried using a prescaler on TMR0 but it didn't fix the missing instructions. I've confirmed the interrupt period by observing the RB1 output. Code attached.
Mod edit: added code tags
Code:
;**********************************************************************
; Li-ion balancer
; PIC16F882, 20MHz, origin
;**********************************************************************
list p=16f882 ; list directive to define processor
#include <p16F882.inc> ; processor specific variable definitions
;errorlevel -302 ; suppress message 302 from list file
__config _CONFIG1, h'20f2' ;
; 0010 - nyi,nyi,debug disabled,LVP off
; 0000 - Failsafe disabled, I/E switchover disabled, BOR disabled
; 1111 - Dataprotection disabled,Codeprotection disabled, MCLR, INTOSC on
; 0010 - Powerup timer ON, WDT off, 20Mhz crystal on OSC1-2
cblock 0x20 ; Begin General Purpose-Register
countLED
nCycles ; cycles per interrupt
w_temp
status_temp
endc
;***** VARIABLE DEFINITIONS
;w_temp EQU 0x71 ; variable used for context saving
;status_temp EQU 0x72 ; variable used for context saving
;**********************************************************************
ORG 0x000 ; processor reset vector
goto setup ; go to beginning of program
ORG 0x004 ; interrupt vector location
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
call isr
; set TMR0 so that we have nCycles per interrupt
movfw nCycles
subwf h'FF',w
movwf TMR0
bcf INTCON,T0IF
bsf INTCON, T0IE ; enable TMR0 interrupt
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
;**********************************************************************
setup ; init PIC16F882
movlw b'00000000' ; Turn off comparator 1
movwf CM1CON0
banksel ANSEL
clrf ANSEL ; 0 = all pins digital ie. analog off
clrf ANSELH
banksel TRISA ; BSF STATUS,RP0 Jump to bank 1 use BANKSEL instead
movlw b'00000000' ; B: all outputs
movwf TRISB
movwf TRISA
movwf TRISC
banksel INTCON ; back to bank 0
clrf PORTA ; all outputs low
clrf PORTB
; setp TMR0 interrupts
banksel OPTION_REG ; Reg. 0x81 BANK1
movlw b'00001000' ; instruction clock, assign prescale to WDT
movwf OPTION_REG
banksel INTCON ;
clrf INTCON
bsf INTCON, GIE ; enable global interrupt
bcf INTCON, PEIE ; enable all unmasked interrupts
bsf INTCON, T0IE ; enable TMR0 interrupt
clrf TMR0
movlw d'1' ; 100 instructions per interrupt = 20us
movwf nCycles
goto main
main
movlw b'00000001' ; toggle 0th bit
xorwf PORTB,f
goto main
;************************************************************************
isr
movlw b'00000010' ; toggle 1st bit every interupt
xorwf PORTB,f
return
END ; directive 'end of program'
Attachments
-
2.9 KB Views: 10
Last edited by a moderator: