PDA

View Full Version : TMR0 Confusion



retepsnikrep
- 1st August 2011, 13:45
Just after a bit of help with TMR0

I have hacked Darrell's SSPWM routine and am now adapting it to use TRM0 instead of TMR1.

Now I note you cant stop/start TMR0 I dont think that's a major issue in my application which is generating a 2khz pwm.

I'm confused with the reloading of the prescaler i'm going to use 1/4 with a preload of 6 and 8mhz int clock to generate an interrupt at 2000hz.

After the interrupt is dealt with and I reload TMR0 with my PWM duty + preload do I have to reassign the prescaler every time?

My hacked start SSPWM code is below.

Config



'OPTION_REG = %00000001 'Set Option Reg for TMR0 and prescaler 1/4


Start SSPWM




StartSPWM: 'Set DutyCycle before calling
'For TMR0 2khz pwm and 8mhz clock Ticks = xxx per cycle
GIE = 1
PEIE = 1
TMR0_ON_TICKS = DutyCycle '(DutyCycle must be between 25 - 225 (10-90%)
TMR0_OFF_TICKS = 255 - TMR0_ON_TICKS
TMR0_ON_VAL = 255 - TMR0_ON_TICKS + 6
TMR0_OFF_VAL = 255 - TMR0_OFF_TICKS + 6

TMR0IE = 1 'Enable TMR0 interrupt enable bit (1 = enabled)
TMR0IF = 0 'Clear TMR0 interrupt flag
TMR0 = 255 'Load TMR0 with 255 First tick will cause an interrupt

1/4 Prescaler setup here ?????

return


My hacked Int routine is below



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 INTCON, TMR0IF ; is TMR0IF set? Timer0 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 ;
MOVF _TMR0_OFF_VAL,W ; 1
ADDWF TMR0,F ; 1 ; reload timer with correct value
GOTO TimerDone ;12/27
TurnON
bsf _CmdPwr ; Set CmdPwr High
bsf _SPWMstate ;
MOVF _TMR0_ON_VAL,W ; 1
ADDWF TMR0,F ; 1 ; reload timer with correct value

TimerDone

1/4 Prescaler setup here ?????

bcf INTCON, TMR0IF ; 1/28 ; Clear Timer0 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

cncmachineguy
- 1st August 2011, 14:59
Prescaler should be set and forget as I understand it

mister_e
- 1st August 2011, 16:18
When you use the USART, are you setting the Baudrate after each character sent? Nope!

When you use the CCP module in PWM mode, do you need to configure the frequency each time you want to play with the duty cycle? Nope!

Internal hardware are often like so, you set them, you forget them.

retepsnikrep
- 1st August 2011, 16:22
That's why i'm confused the 12F683 data sheet says that writes to the TMR0 reg clear the prescaler :?



The prescaler is not readable or writable. When
assigned to the Timer0 module, all instructions writing to
the TMR0 register will clear the prescaler.

mister_e
- 1st August 2011, 16:25
mm, seems I need to send my crystal ball again for repair... she don't want to tell me the PIC you're using ;)

cncmachineguy
- 1st August 2011, 16:30
That can be a little confusing. the prescaler keeps a count. Say it is set up for 1:8, it will count to 8 then roll over. the roll over is the new tmr count. When you write the tmr0 they are saying the count in pre scale will be reset back to 0. so if it had a count of 5, it will be cleared to zero. But the amount of pre scale will persist, it will still be 1:8

Steve, she just needs glasses, look above the quote

retepsnikrep
- 1st August 2011, 17:58
Thanks for that CNC! makes sense. I'm using a 12F683 FYI. I'll do some bench testing

HenrikOlsson
- 2nd August 2011, 16:03
Hi,

Now I note you cant stop/start TMR0 I dont think that's a major issue in my application which is generating a 2khz pwm.
You can't stop TMR0 when its in timer mode but you can switch it from timer- to counter mode which, as long as you don't have a any pulses coming on the T0CKI pin, will have the same effect as stopping it. As always YMMV but it's a "trick" that might work.

/Henrik.

retepsnikrep
- 2nd August 2011, 16:18
Hi,

You can't stop TMR0 when its in timer mode but you can switch it from timer- to counter mode which, as long as you don't have a any pulses coming on the T0CKI pin, will have the same effect as stopping it. As always YMMV but it's a "trick" that might work.

/Henrik.

That's sneaky!! :)

Darrel Taylor
- 2nd August 2011, 19:53
With Timer0 on 16F's, there's no reason to stop the timer while reloading since it's an 8-bit timer.

With 16-bit timers there is the slim possibility that the lowbyte will overflow to the highbyte at the same time you are reloading it.
But that can't happen with an 8-bit timer, so just reload the 8-bit value and don't worry about it.

retepsnikrep
- 4th August 2011, 07:26
Thanks it's working on the bench now just need to check my TMR0 calculations.

Using http://eng-serve.com/pic/pic_timer.html I get a prescaler of 1/4 and preload of 6 giving 500us interrupts (2khz) so that gives me 250 ticks per cycle with 8mhz clock.

That works out at 2.5ticks per 1% duty.
So for 10% duty I need to load 25 + 6 into TMR0 for the 90% off part of the cycle? and 225 + 6 for the 10% on part of the cycle?
Does that look sound right?

So my modified code looks like this.



TMR0_ON_TICKS = DutyCycle '(DutyCycle must be between 25 - 225 (10-90%)
TMR0_OFF_TICKS = 250 - TMR0_ON_TICKS
TMR0_ON_VAL = 250 - TMR0_ON_TICKS + 6
TMR0_OFF_VAL = 250 - TMR0_OFF_TICKS + 6

retepsnikrep
- 4th August 2011, 21:10
Although this appears to be working in my application I'm confused by

PEIE var INTCON.6 'Peripheral Interrupt enable

(Does this need to be on for TMR0 interrupt?) I currently have it enabled.

I understand PEIE needs to be enabled for TMR1 but TMR0?

retepsnikrep
- 5th August 2011, 20:07
Appears not as seems to be working without it set?

Darrel Taylor
- 5th August 2011, 21:26
In the Interrupts section of the datasheet (under SPECIAL FEATURES OF THE CPU), there is a diagram that shows the Interrupt Logic.

Only the peripherals in the red box are affected by PEIE.

5841

retepsnikrep
- 6th August 2011, 01:10
Thanks Darrel that's very clear, little by little i'm learning.

retepsnikrep
- 19th August 2011, 11:55
How long to execute the reload?

I'm now using the timers for a few things but how do you work out the value to add on to the reload value for the time it takes to do the reload?




T1CON.0 = 0 'Stops Timer

TMR1RunOn.Highbyte = TMR1H 'Load the Run-On (Over-Run) value (if any)
TMR1RunOn.Lowbyte = TMR1L 'Load the Run-On (Over-Run) value (if any)
TMR1RunOn = PreLoad + TMR1RunOn 'Calculate new Preload setting to include any timer overrun
TMR1H = TMR1RunOn.HighByte 'Load the timer with new value
TMR1L = TMR1RunOn.LowByte 'Load the timer with new value
PIR1.0 = 0 'Clear TMR1 int flag
T1CON.0 = 1 'Starts Timer


The above for instance how much to add to keep the accuracy? How long does that all take? Any rough estimates? It's a pretty standard reload code but I could not find any examples. I'm running at 8mhz with 1/8 prescaler.