This is this Multi_SPWM.pbp file:



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