Here are a few ways to do this without using a slower osc.
For a PIC12F1822 using a compare interrupt.
Code:
@ __config _CONFIG1, _FOSC_INTOSC & _MCLRE_OFF & _CLKOUTEN_OFF
@ __config _CONFIG2, _PLLEN_OFF & _LVP_OFF
DEFINE INTHAND HzOut
LED VAR PORTA.0
TRISA = 0
ANSELA = 0 ' All digital
CCP1CON = %00001011 ' Compare mode with auto reset of Timer1
CCPR1H = $06 ' Load for match every 1,538uS
CCPR1L = $02 ' 1,538uS x 2 = 3.076mS. 1/3.076mS = ~325.09 Hz
OSCCON = %01101000 ' 4MHz internal osc
T1CON = %00000001 ' Enable Timer1, 1:1 rescale
PIR1.2 = 0 ' Clear int flag before enabling interrupt
PIE1 = %00000100 ' Enable CCP1 interrupt
INTCON = %11000000 ' Global & peripheral ints enabled
Main:
TOGGLE LED ; Do whatever here. You have ~1,538 instruction
PAUSE 1000 ; cycles before each interrupt
GOTO Main
ASM
HzOut ; Eats-up 5 instruction cycles
MOVLW B'00000100' ; Load WREG with %00000100 for XOR op below
XORWF PORTA,F ; Toggle PORTA,2 on each 1/2 cycle
BCF PIR1,CCP1IF ; Clear CCP1 interrupt flag
RETFIE ; Go get some more
ENDASM
END
And one for the 12F683 using Timer2/PR2 match interrupt;
Code:
@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
DEFINE INTHAND HzOut
wsave VAR BYTE $70 SYSTEM
ssave VAR BYTE BANK0 SYSTEM
psave VAR BYTE BANK0 SYSTEM
LED VAR GPIO.0
TRISIO = 0
ANSEL = 0 ' All digital
CMCON0 = 7
OSCCON = %01100000 ' 4MHz internal osc
T2CON = %00111100 ' Enable Timer2, 1:1 prescale / 1:8 postscale
PIR1.1 = 0 ' Clear TMR2 int flag before enabling interrupt
PIE1 = %00000010 ' Enable TMR2 interrupt
INTCON = %11000000 ' Global & peripheral ints enabled
PR2 = 191
Main:
TOGGLE LED ; Do whatever here.
PAUSE 1000 ;
GOTO Main
ASM
HzOut
movwf wsave ; Save W
swapf STATUS,W ; Swap STATUS to W (swap avoids changing STATUS)
clrf STATUS ; Clear STATUS
movwf ssave ; Save swapped STATUS
movf PCLATH,W ; Move PCLATH to W
movwf psave ; Save PCLATH
MOVLW B'00000100' ; Load WREG with %00000100 for XOR op below
XORWF GPIO,F ; Toggle GPIO,2 on each 1/2 cycle
BCF PIR1,TMR2IF ; Clear TMR2 interrupt flag
movf psave,W ; Retrieve PCLATH value
movwf PCLATH ; Restore it to PCLATH
swapf ssave,W ; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
movwf STATUS ; Restore it to STATUS
swapf wsave,F ; Swap the stored W value
swapf wsave,W ; Restore it to W (swap to avoid changing STATUS)
retfie ; Go get some more
ENDASM
END
Interrupts are a LOT faster & easier with newer PIC types with auto context save/restore.
Bookmarks