That wouldn't be PWM.
It would be a variable frequency generator.
Much easier to do, but you don't need SSPWM.
That wouldn't be PWM.
It would be a variable frequency generator.
Much easier to do, but you don't need SSPWM.
DT
Just as a final follow up I hacked SSPWM down to a fraction of it's original size and it works great.
I use the 8mhz internal osc and for my reqd 2000hz freq that works out at a very simple 1000 ticks per cycle![]()
I use a word variable for DutyCycle between 0-1000 which gives me a 0.1% resolution now a tenfold increase over the original.
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 ************************************
I just load DutyCyle with my reqd duty and call StartSPWM:
Thanks to Darrel for the original code which I now understand as well making some small personal inroads into Pic Assembler![]()
A couple more questions about this Darrel as i'm trying to understand the code.
In your variable definitions we have
These are not anywhere else in the code? so i don't understand how they are used?Code: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
I tried removing them and the program compiled correctly but started giving an eroneous display?
In your Int code you have
What does " if (CODE_SIZE <= 2)" do?Code: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
Clearly it jumps over the register saving stuff but where does CODE_SIZE come from?
2 does that mean 2k or 2 words, bytes?
Thanks Peter
PS I have bought PBP3 looking forward to trying it later![]()
This post should cover both of those questions.
http://www.picbasic.co.uk/forum/show...9101#post89101
And yes, 2 means 2K.
It is set in the .bas or .pbpinc files.
DT
Thanks for that interesting link.
Finally to confirm. using a 16F88 which has 4k of code space I can dispense with.
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
But with a 12F683 2k space i need it.
I just bough & installed PBP3 looks good and after tweaking configs looks ok. Does this config look alright for a 16F88?
it compiles ok.Code:#config __config _CONFIG1, _INTRC_IO & _WDT_OFF & _LVP_OFF & _MCLR_ON & _CCP1_RB3 __config _CONFIG2, _IESO_OFF & _FCMEN_OFF #endconfig
Yes you could dispense with it if you really wanted.
But the assembler will do that for you if the chip has more than 2K of program space.
Then by leaving it in, it will still work on any other 14-bit core chip too.
The #config block looks great.
DT
Hi,
CONFIGs look alright to me.
As for the context save stub I don't think you need to remove or do anything. The IF(CODE_SIZE<=2k) tells the assembler to automatically insert that piece code when and only when you HAVE a chip with 2k or less, if the chip has more than 2k the statement evalutates false and the code won't get it inserted. Automagically....
Obviously you CAN remove it when using the F88 but there's really no need to as I see it.
/Henrik.
EDIT: OK that made my post pretty redundant, went for a cup of coffee and Darrel beat me to it.
Bookmarks