you have to use one of the timers to do the division by 193, and not the
isr.
an isr is much too slow to handle all these interrupts, coming every 5us
with this design.
so your pulse is now about
(time, required by the isr) / 5us = pulselength [s]
good luck!
tino
Somehow my clock ckt seems to be running a lot slower than it should, but
I'm stumped. Here are some details...
Swapped 32.768 khz crystal/caps for a 1.544 MHz external oscillator, into
an 16F872 circuit. This is an ECS-200 series oscillator in a 14-pin metal
pkg, but only has 4 pins, and only 3 of those are active -- +ve, gnd, and
out
(which I connected to OSC1/CLKIN). OSC2/CLKOUT is now open.
Pre-scaler is now 1:8 and ISR routine divides a few times: first by 193,
then by 25, then by 10, to give me 1-sec pulses. (There's a reason for
those divisors in case you're wondering -- I can get 0.1 sec pulses I need
for something else).
However, it's running MUCH slower than that -- taking a few minutes to
generate a 1-sec pulse!
Am I missing something here? I've left the osc config bits to LP, and
verified the ext osc freq with an oscilloscope. Also, there's a setting
in
OPTION_REG for selecting the source clock for TMR0 to internal or
T0CKI, but I don't think this setting has anything to do with this prob.
Any ideas why I may be seeing these results?
Cheers,
-Neil.
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
Not sure what you mean by "use one of the timers" I am using
the prescaler in div-by-8 mode, so the ISR gets called at a
freq of 48250Hz. That's when I divide by 193 in the ISR, etc.
I could adjust the prescaler to div-by-16, but the freq is
not further divisible by any multiple of 2 after that.
So you're suggesting that my ISR does not get completed before
another TMR0 interrupt is generated, so some interrupts go
ignored?
Here is some code sections that better explain what I'm doing...
;-------------------------------------------------------------------
; Interrupt Service Routine
;-------------------------------------------------------------------
ISR:
;----- Save W and STATUS registers -----
movwf TMP_W ; Save W
swapf STATUS,W ; Get status (w/o affecting status bits)
movwf TMP_ST ; Save status
;----- [ Freq. here = 1.544Mhz / (4 * 8) ] -----
;----- Divide TMR0 by 193 to get 1/250-sec pulses -----
decf SCALER0,F
btfss STATUS,Z ; Reached 0?
goto ISRDone ; Nothing else to be done for now
movlw D'193'
movwf SCALER0 ; Reset to 193
;----- Divide by 25 to get 1/10-sec pulses -----
decf SCALER1,F
btfss STATUS,Z ; Reached 0?
goto ISRDone ; Nothing else to be done for now
movlw D'25'
movwf SCALER1 ; Reset to 25
;----- Get and preprocess button -----
movf BUTTONS,W ; Take button states and...
movwf BUTTONS_PREV ; ... hold it as prev buttons
movf PORTB,W ; Get new button values
movwf BUTTONS ; Hold it
call ButtonProc
call ButtonActions
;----- Divide by 10 to get 1 sec pulses -----
decf SCALER2,F
btfss STATUS,Z ; Reached 0?
goto ISRDone ; Nothing else to be done for now
movlw D'10'
movwf SCALER2 ; Reset to 10
;----- [ Period here = 1 sec ] -----
BYPASS1:
;---------------------------------------------------------
; From this point, all actions occur at 1-sec intervals
;---------------------------------------------------------
<code snipped>
ISRDone:
;----- Restore W and STATUS registers -----
swapf TMP_ST,W ; Get status (w/o affecting status bits)
movwf STATUS ; Put it back into STATUS
swapf TMP_W,F ; Swap W nibbles (w/o affecting status bits)
swapf TMP_W,W ; Swap W nibbles again and put into W
bcf INTCON,T0IF ; Reset TMR0 interrupt flag
retfie
Just tried changing the pre-scaler to 1:32 but this did not solve
the problem -- my guess is that if it works with the 32khz xtal,
then it should work with the 1.544mhz external clock, but just
much faster. But that's not what I'm seeing here.
> 1.544 MHz external oscillator .... (which I connected to
> OSC1/CLKIN). OSC2/CLKOUT is now open.
>
> Pre-scaler is now 1:8 and ISR routine divides a few times: first by
> 193, then by 25, then by 10, to give me 1-sec pulses. (There's a
> reason for those divisors in case you're wondering -- I can get 0.1
> sec pulses I need for something else).
>
> However, it's running MUCH slower than that -- taking a few minutes to
> generate a 1-sec pulse!
Neil:
Lemme guess... It's taking exactly 4 minutes and 16 seconds per "1-
second" pulse, right?
I think you're misunderstanding how the TMR0 interrupt works. The
TMR0 register is incremented by the prescaler, but the TMR0 interrupt
doesn't fire until the TMR0 register overflows from 255 to 0... So
your interrupts are actually happening at 1/256 the rate that you
thought.
Does that explain the behavior you're seeing?
-Andy
=== Andrew Warren -- EraseMEaiwspam_OUTTakeThisOuTcypress.com
=== Principal Design Engineer
=== Cypress Semiconductor Corporation
===
=== Opinions expressed above do not
=== necessarily represent those of
=== Cypress Semiconductor Corporation
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
Don't ask -- I think I just need more sleep or something.
As you were typing this email, I realized the flaw. Switched
back to the 32.768khz crystal, saw the (correct) timing and
was looking at the code for that, when I realized I'm
accounting for the 256 in that code, but not in the 1.544Mhz
code.
I think that train of thought started when I was trying
to find the factors of 1,544,000 Hz for the dividers, and
being non-divisible by 256, I somehow managed to ignore it.
Okay, it's confirmed, I'm brain-dead.
Guess what I really need to do is set TMR0 to 255-193 on
each interrupt cycle and drop my SCALER0 altogether.
> Don't ask -- I think I just need more sleep or something.
> As you were typing this email, I realized the flaw. Switched
> back to the 32.768khz crystal, saw the (correct) timing and
> was looking at the code for that, when I realized I'm
> accounting for the 256 in that code, but not in the 1.544Mhz
> code.
>
> I think that train of thought started when I was trying
> to find the factors of 1,544,000 Hz for the dividers, and
> being non-divisible by 256, I somehow managed to ignore it.
>
> Okay, it's confirmed, I'm brain-dead.
>
> Guess what I really need to do is set TMR0 to 255-193 on
> each interrupt cycle and drop my SCALER0 altogether.
>
> Thanks much,
> -Neil.
>
>
>
The calculation (adding 2) is straightforward, but what
do you mean by "jitter". I remember seeing something on
this a while back (either in the archives or on piclist.org),
but never got a clear explanation of jitter. Care to
add some enlightenment?
The datasheet also states that the prescaler is cleared
whenever TMR0 is written to. My understanding is that
the pre-scaler "counts" before TMR0 (since it's the TMR0
transition that triggers the interrupt), so I'm wondering
if modifying TMR0 will cause the clock to run slow due
to the prescaler getting reset when it shouldn't?
Does it even matter? A quick calculation tells me with
a 1:8 prescaler, say for example the prescaler gets reset
to 0 whenever it just hits its 7th pulse from start.
That means that it loses 7*4*osc-period units of time.
It would do this whenever TMR0 gets reset to 193, which
means every 8*4*193*osc-period units of time. So time
loss ~= 1 pulse in every 222. That means about 39.5 days
a year.
That's pretty significant, if it really happens. Does it?
Or am I totally off on the wrong tangent here?
> Bob,
>
> The calculation (adding 2) is straightforward, but what
> do you mean by "jitter". I remember seeing something on
> this a while back (either in the archives or on piclist.org),
> but never got a clear explanation of jitter. Care to
> add some enlightenment?
I am not sure if it happens with TMR0 or not, but some interrupt sources
have different latencies depending on whether a one- or two-clock
instruction is executing when the interrupt occurs.
> The datasheet also states that the prescaler is cleared
> whenever TMR0 is written to. My understanding is that
> the pre-scaler "counts" before TMR0 (since it's the TMR0
> transition that triggers the interrupt), so I'm wondering
> if modifying TMR0 will cause the clock to run slow due
> to the prescaler getting reset when it shouldn't?
Yeah, I assumed you were not using the prescaler. This technique will _not_
work with the prescaler at any setting other than 1:1.
> Does it even matter? A quick calculation tells me with
> a 1:8 prescaler, say for example the prescaler gets reset
> to 0 whenever it just hits its 7th pulse from start.
> That means that it loses 7*4*osc-period units of time.
> It would do this whenever TMR0 gets reset to 193, which
> means every 8*4*193*osc-period units of time. So time
> loss ~= 1 pulse in every 222. That means about 39.5 days
> a year.
>
> That's pretty significant, if it really happens. Does it?
> Or am I totally off on the wrong tangent here?
No, you aren't off on a tangent. This is exactly the thing that can happen.
> Thanks,
> -Neil.
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads