DEFINE INTHAND INT_CODE ' Tell PBP Where the code starts on an interrupt
wsave VAR BYTE $20 SYSTEM '$20 Save location for the W register if in bank0
wsave1 VAR BYTE $A0 SYSTEM ' Save location for the W register if in bank1
wsave2 VAR BYTE $120 SYSTEM ' Save location for the W register if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' Save location for the W register if in bank3
ssave VAR BYTE Bank0 SYSTEM ' Save location for the STATUS register
psave VAR BYTE Bank0 SYSTEM ' Save location for the PCLATH register
TMR1_ON_TICKS var word Bank0 ' # of Tmr ticks for On Time
TMR1_OFF_TICKS var word Bank0 ' # of Tmr ticks for Off Time
TMR1_ON_VAL var word Bank0 ' # to load TMR1 for On Time
TMR1_OFF_VAL var word Bank0 ' # to load TMR1 for Off Time
DataFlags var byte Bank0
SPWMstate var DataFlags.2 ' Current state of SPWM output high or low
GIE var INTCON.7
PEIE var INTCON.6
TMR1IE var PIE1.0
TMR1ON var T1CON.0
clear 'Clear All Variables
goto Start
' ------------------------------------------------------------------------
asm
INT_CODE
if (CODE_SIZE <= 2)
movwf wsave ; copy W to wsave register
swapf STATUS,W ; swap status reg to be saved into W
clrf STATUS ; change to bank 0 regardless of current bank
movwf ssave ; save status reg to a bank 0 register
movf PCLATH,w ; move PCLATH reg to be saved into W reg
movwf psave ;6 ; save PCLATH reg to a bank 0 register
endif
btfss PIR1, TMR1IF ; is TMR1IF set? Timer1 Interrupt Flag
GOTO NoTimerInt ; No. Bypass timer load
btfss _SPWMstate ; Is Output High?
GOTO TurnON ;9/15 ; No.
TurnOFF
bcf _CmdPwr ; Set CmdPwr Low
bcf _SPWMstate ;
BCF T1CON,TMR1ON ; Turn off timer
MOVF _TMR1_OFF_VAL,W ; 1
ADDWF TMR1L,F ; 1 ; reload timer with correct value
BTFSC STATUS,C ; 1/2
INCF TMR1H,F ; 1
MOVF _TMR1_OFF_VAL+1,W ; 1
ADDWF TMR1H,F ; 1
BSF T1CON,TMR1ON ; 1 ; Turn it back on
GOTO TimerDone ;12/27
TurnON
bsf _CmdPwr ; Set CmdPwr High
bsf _SPWMstate ;
bcf T1CON,TMR1ON ; Turn off timer
MOVF _TMR1_ON_VAL,W ; 1
ADDWF TMR1L,F ; 1 ; reload timer with correct value
BTFSC STATUS,C ; 1/2
INCF TMR1H,F ; 1
MOVF _TMR1_ON_VAL+1,W ; 1
ADDWF TMR1H,F ; 1
bsf T1CON,TMR1ON ; 1 ; Turn it back on
TimerDone
bcf PIR1, TMR1IF ; 1/28 ; Clear Timer1 Interrupt Flag
NoTimerInt
Movf psave,w ; Restore the PCLATH reg
Movwf PCLATH
swapf ssave,w ; Restore the STATUS reg
movwf STATUS
swapf wsave,f
swapf wsave,w ; 6/34 ; Restore W reg
Retfie ; Exit the interrupt routine
endasm
' ------------------------------------------------------------------------
StartSPWM: 'Set Freq and DutyCycle before calling
'For 2khz pwm and 8mhz clock Ticks = 1000 per cycle
GIE = 1
PEIE = 1
TMR1H = 255 'Load TMR1 with 65535, First tick will cause
TMR1L = 255 'an interrupt that will load TMR1_???_VAL
TMR1_ON_TICKS = DutyCycle '(Must be between 100 & 900 (10-90%)
TMR1_OFF_TICKS = 1000 - TMR1_ON_TICKS
TMR1_ON_VAL = 65535 - TMR1_ON_TICKS + 8
TMR1_OFF_VAL = 65535 - TMR1_OFF_TICKS + 8
TMR1IE = 1
T1CON = 1 'Set Timer1 prescaler to 1 and turn Timer1 on
return
'************************************************* ************************************
'*********************************** Main Program ************************************
Bookmarks