Code:
'****************************************************************
'* Name : Multi_SPWM.pbp *
'* Author : Darrel Taylor *
'* Notice : Copyright (c) 2003 *
'* Date : May 16, 2004 *
'****************************************************************
DEFINE INTHAND INT_CODE ' Tell PBP Where the code starts on an interrupt
wsave var byte $20 SYSTEM ' location for W if in bank0
' --- IF any of these three lines cause an error ?? Simply Comment them out to fix the problem ----
wsave1 var byte $A0 SYSTEM ' location for W if in bank1
wsave2 var byte $120 SYSTEM ' location for W if in bank2
wsave3 var byte $1A0 SYSTEM ' location for W if in bank3
' ------------------------------------------------------------------------------
ssave var byte BANK0 SYSTEM ' location for STATUS register
psaveU var byte BANK0 SYSTEM ' location for PCLATU register
psave var byte BANK0 SYSTEM ' location for PCLATH register
bsave var byte BANK0 SYSTEM ' location for BSR register
DutyCount VAR byte
ASM
ifdef SPWMFREQ
FOSC4 = OSC * 1000000 / 4
IntFREQ = SPWMFREQ * 256
TimerCount = FOSC4 / IntFREQ
TimerConst = 65536 - TimerCount + 7
endif
ENDASM
ASM
InitPin macro Port, Pin
MOVE?CT 0, Port, Pin ; Make Port.Pin LOW
ifdef BSR ; if chip is 16-bit ; Set TRIS to output
MOVE?CT 0, ((Port) + 12h), Pin
else ; chip is 14-bit
MOVE?CT 0, ((Port) + 80h), Pin
endif
endm
ENDASM
ASM
SPWMActive = 0
; ----------------------------------------------------------------------------1-
SPWM1used = 0
ifdef _SPWM1PIN
ifdef SPWM1VAR
SPWM1used = 1
SPWMActive = 1
InitPin _SPWM1PIN
else
error "SPWM1VAR must be defined to use SPWM1PIN"
endif
else
ifdef SPWM1VAR
error "SPWM1PIN must be defined to use SPWM1VAR"
endif
endif
; ----------------------------------------------------------------------------2-
SPWM2used = 0
ifdef _SPWM2PIN
ifdef SPWM2VAR
SPWM2used = 1
SPWMActive = 1
InitPin _SPWM2PIN
else
error "SPWM2VAR must be defined to use SPWM2PIN"
endif
else
ifdef SPWM2VAR
error "SPWM2PIN must be defined to use SPWM2VAR"
endif
endif
; ----------------------------------------------------------------------------3-
SPWM3used = 0
ifdef _SPWM3PIN
ifdef SPWM3VAR
SPWM3used = 1
SPWMActive = 1
InitPin _SPWM3PIN
else
error "SPWM3VAR must be defined to use SPWM3PIN"
endif
else
ifdef SPWM3VAR
error "SPWM3PIN must be defined to use SPWM3VAR"
endif
endif
; ----------------------------------------------------------------------------4-
SPWM4used = 0
ifdef _SPWM4PIN
ifdef SPWM4VAR
SPWM4used = 1
SPWMActive = 1
InitPin _SPWM4PIN
else
error "SPWM4VAR must be defined to use SPWM4PIN"
endif
else
ifdef SPWM4VAR
error "SPWM4PIN must be defined to use SPWM4VAR"
endif
endif
; ----------------------------------------------------------------------------5-
SPWM5used = 0
ifdef _SPWM5PIN
ifdef SPWM5VAR
SPWM5used = 1
SPWMActive = 1
InitPin _SPWM5PIN
else
error "SPWM5VAR must be defined to use SPWM5PIN"
endif
else
ifdef SPWM5VAR
error "SPWM5PIN must be defined to use SPWM5VAR"
endif
endif
; ----------------------------------------------------------------------------6-
SPWM6used = 0
ifdef _SPWM6PIN
ifdef SPWM6VAR
SPWM6used = 1
SPWMActive = 1
InitPin _SPWM6PIN
else
error "SPWM6VAR must be defined to use SPWM6PIN"
endif
else
ifdef SPWM6VAR
error "SPWM6PIN must be defined to use SPWM6VAR"
endif
endif
; ----------------------------------------------------------------------------7-
SPWM7used = 0
ifdef _SPWM7PIN
ifdef SPWM7VAR
SPWM7used = 1
SPWMActive = 1
InitPin _SPWM7PIN
else
error "SPWM7VAR must be defined to use SPWM7PIN"
endif
else
ifdef SPWM7VAR
error "SPWM7PIN must be defined to use SPWM7VAR"
endif
endif
; ----------------------------------------------------------------------------8-
SPWM8used = 0
ifdef _SPWM8PIN
ifdef SPWM8VAR
SPWM8used = 1
SPWMActive = 1
InitPin _SPWM8PIN
else
error "SPWM8VAR must be defined to use SPWM8PIN"
endif
else
ifdef SPWM8VAR
error "SPWM8PIN must be defined to use SPWM8VAR"
endif
endif
EndASM
ASM
; ----------------- ADD TimerConst to TMR1H:TMR1L
ADD2_TIMER macro
CHK?RP T1CON
BCF T1CON,TMR1ON ; Turn off timer
MOVLW LOW(TimerConst) ; 1
ADDWF TMR1L,F ; 1 ; reload timer with correct value
BTFSC STATUS,C ; 1/2
INCF TMR1H,F ; 1
MOVLW HIGH(TimerConst) ; 1
ADDWF TMR1H,F ; 1
endm
ENDASM
ASM
; ----------------- ADD TimerConst to TMR1H:TMR1L and restart TIMER1
RELOAD_TIMER macro
ADD2_TIMER
BSF T1CON,TMR1ON ; 1 ; Turn TIMER1 back on
CHK?RP PIR1
bcf PIR1, TMR1IF ; Clear Timer1 Interrupt Flag
endm
ENDASM
ASM
; ----------------- Load TimerConst into TMR1H:TMR1L
LOAD_TIMER macro
MOVE?CB 0, T1CON ; Turn OFF Timer1
MOVE?CB 0, TMR1L ; Reset Timer1 to 00:00
MOVE?CB 0, TMR1H
ADD2_TIMER
endm
EndAsm
; ----------------- Start PWM's (IF active) ----------------------------------
ASM
ifdef SPWMFREQ
if SPWMActive == 1
LOAD_TIMER
CHK?RP PIE1
bsf PIE1, TMR1IE ; Enable Timer1 Interrupts
CHK?RP INTCON
bsf INTCON, PEIE ; Turn ON peripheral interrupts
bsf INTCON, GIE ; Turn ON global interrupts
CHK?RP PIR1
bcf PIR1, TMR1IF
bsf T1CON, TMR1ON ; Turn ON Timer1
else
messg "SPWMFREQ has been defined, but no SPWM channels are allocated"
endif
else
if SPWMActive == 1
error "SPWMFREQ must be defined to use any SPWM channels"
else
messg "Multi_SPWM included but no Channels have been defined"
endif
endif
ENDASM
Goto Over_Code
Asm
INT_START macro
ifdef BSR ; if chip is 16-bit
movff WREG, wsave ;6 Wreg
; movff PCLATU, psaveU ;8 PCLATU
; movff PCLATH, psave ;10 PCLATH
movff STATUS, ssave ;12 STATUS
movff BSR, bsave ;14 BSR
SaveCycles = 10
else ; chip is 14-bit
if (CODE_SIZE <= 2) ;4 cycles to push PC and jump to Int_Code
movwf wsave ;5 copy W to wsave register
swapf STATUS,W ;6 swap status reg to be saved into W
clrf STATUS ;7 change to bank 0 regardless of current bank
movwf ssave ;8 save status reg to a bank 0 register
movf PCLATH,w ;9 move PCLATH reg to be saved into W reg
movwf psave ;10 save PCLATH reg to a bank 0 register
endif
SaveCycles = 10
endif
endm
EndAsm
Asm
INT_RETURN macro
ifdef BSR ; if chip is 16-bit
movff bsave, BSR ;2 BSR
movff ssave, STATUS ;4 STATUS
; movff psaveU, PCLATU ;6 PCLATU
; movff psave, PCLATH ;8 PCLATH
movff wsave, WREG ;6 WREG
RestoreCycles = 10 ;10 - add 4 to POP and return
else ; chip is 14-bit
; movf psave,w ;1 Restore the PCLATH reg
; movwf PCLATH ;2
swapf ssave,w ;1 Restore the STATUS reg
movwf STATUS ;2
swapf wsave,f ;3
swapf wsave,w ;4 Restore W reg
RestoreCycles = 8 ;8 - add 4 to POP and return
endif
retfie ; Return from Interrupt
endm
EndAsm
ASM
SPWMint macro Port, Pin, DutyVar ; Interrupt code for each Pin
local NotIdle, IdleHigh, SPWMdone, StartAdd1, EndAdd1, StartAdd2, EndAdd2
StartAdd1 = $
MOVE?BA DutyVar ; Copy DutyVar to W reg
btfss STATUS, Z ; if DutyVar = 0
goto NotIdle ; No, Skip Idle
EndAdd1 = $
CHK?RP Port ; YES, then idle Low
bcf Port, Pin ; Set Pin Low
goto SPWMdone
NotIdle
StartAdd2 = $
MOVE?BA _DutyCount ; Copy DutyCount to W reg
CHK?RP DutyVar ; Select proper bank
subwf DutyVar, W ; Subtract DutyVar from DutyCount
MOVE?TT STATUS,C, Port,Pin ; Copy carry bit to Port/Pin
EndAdd2 = $
SPWMdone
ifdef BSR ; if chip is 16-bit core
InstCount = InstCount + ((EndAdd1 - StartAdd1 + EndAdd2 - StartAdd2) / 2)
else ; chip is 14-bit core
InstCount = InstCount + (EndAdd1 - StartAdd1 + EndAdd2 - StartAdd2)
endif
endm
ENDASM
; ------- Interrupt Code -------------------------------------------------------
ASM
INT_CODE
InstCount = 0
INT_START
CHK?RP PIR1
btfss PIR1, TMR1IF
goto NoTMR1Int
RELOAD_TIMER
if SPWM1used == 1
SPWMint _SPWM1PIN, SPWM1VAR
endif
if SPWM2used == 1
SPWMint _SPWM2PIN, SPWM2VAR
endif
if SPWM3used == 1
SPWMint _SPWM3PIN, SPWM3VAR
endif
if SPWM4used == 1
SPWMint _SPWM4PIN, SPWM4VAR
endif
if SPWM5used == 1
SPWMint _SPWM5PIN, SPWM5VAR
endif
if SPWM6used == 1
SPWMint _SPWM6PIN, SPWM6VAR
endif
if SPWM7used == 1
SPWMint _SPWM7PIN, SPWM7VAR
endif
if SPWM8used == 1
SPWMint _SPWM8PIN, SPWM8VAR
endif
CHK?RP _DutyCount
incf _DutyCount, F
NoTMR1Int
; ---- Test for other interrupts here (If needed) ------------------------------
INT_RETURN
ENDASM
; ------- End of Interrupt Code ------------------------------------------------
ASm
InstCount = InstCount + SaveCycles + RestoreCycles
BetweenInts = TimerCount - InstCount
if (BetweenInts < 0)
error Current SPWM configuration is INVALID - There is no time left between interrupts
messg 1 - "Try using a SPWMFREQ lower than" SPWMFREQ
messg 2 - Use a faster cyrstal than OSC Mhz
messg 3 - Use fewer SPWM channels
endif
ENDASM
Over_Code:
[TabIndex]
Value=0
Bookmarks