Pic Timer questions

Thread Starter

Art

Joined Sep 10, 2007
806
Hi Guys :)

I have a midrange pic using timer1 interrupt on overflow to count 100 Hz cycles.
The example I have seen in asm jumps to interrupt on overflow, disables timer1,
loads a new value to start counting from again into timer1 high and low bytes, and then restarts the timer again.
I guess the instruction time it takes to jump to ISR and reload the value is factored into the value that
is reloaded into timer1.

My question is to do with syncing the signal produced by the chip with another signal not generated by the circuit.
I want to align them in or out of phase by either adding to the constant value loaded to timer1 just enough to shift it in phase before going back to the normal value again.

Is there any consequence of incrementing or decrementing one of the timer1 bytes while it’s counting?
That way I figure would be the easiest way to add or subtract one instruction cycle beat, even if it took more
cycle time to do it.

The only other way I can think of that seem overcomplicated in hardware would be to find a way to pull down individual clock pulses driving the pic’s clock input.
Cheers, Art.
 

JohnInTX

Joined Jun 26, 2012
4,787
Is there any consequence of incrementing or decrementing one of the timer1 bytes while it’s counting?
Probably. You'd have to determine what happens when you write one of the timer registers at the instant its incremented by the clock input. I wouldn't mess with it.

You might try using TMR1/CCP1 in the compare mode to generate a period register (use the mode that automatically clears TMR1 when it reaches the value stored in CCP1REGH/L). Interrupt on the compare (CCP1IF). When that happens, you can tweak the count in CCP1REGH/L to adjust the period. I would set it up so that the next value for CCP1REGH/L is pre-computed based on the last sample. Then on interrupt, just copy the calculated values to CCP1REGH/L. You don't have to mess with TMR1 at all so you don't have problems with trying to modify it on the fly. All you have to do is get the interrupt serviced before the timer counts up to the new CCP values. Be sure to clear CCP1IF after loading the compare registers with their new values.

I don't have easy access to a datasheet so may have misspelled some of the register names. Also, be sure to read the TIMER 1 errata for your chip. Most have some problems with external clocks but the Capture/Compare works fine.
Good luck.
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,377
I guess the instruction time it takes to jump to ISR and reload the value is factored into the value that is reloaded into timer1.
That value is pretty easy to figure out using the simulator and stopwatch built into MPLAB. Guess a value, run the simulator, and see what happens. Adjust the value, recompile, wash, rinse, repeat.
I want to align them in or out of phase by either adding to the constant value loaded to timer1 just enough to shift it in phase before going back to the normal value again.
OK, though you do not mention how you will detect this external event. Going to monitor some pin value?
Is there any consequence of incrementing or decrementing one of the timer1 bytes while it’s counting? That way I figure would be the easiest way to add or subtract one instruction cycle beat, even if it took more cycle time to do it.
About the only thing is your timer period will go a bit whacky during the adjustment portion.
 

Thread Starter

Art

Joined Sep 10, 2007
806
Thanks for the replies.
@ErnieM, yes I can watch a pin value toggled at interrupt and compare that to another signal on a 2 channel scope.

I suppose I can try decrementing the timer value by something like half of the reloaded constant value,
ans see if that makes the timing close to twice as slow.

@jpanhalt, A couple of things.. I tried to describe the problem in a generic fashion.
At the moment I’m trying to sync time with a pulse from GPS,
and later using a freq doubler to run a second micro twice the speed of the first. It might be favourable to align them so that
every fourth clock cycle beats together with the faster pic’s instruction time as well (I’m not sure there’s a need for the later yet).
 

John P

Joined Oct 14, 2008
2,026
I wouldn't try doing anything to the timer while it's running because it's 16 bits, and you can only read or write the upper or lower byte in one instruction, and there could be a problem coodinating the two bytes in time. It's much easier to stop the timer, do what you need to do, and restart it. Or your processor may have an input which captures the timer value to a pair of registers, and generates an interrupt if you want it to.

Rather than worry about time lost responding to an interrupt, you can leave the value in the timer when you do respond, then stop the timer and add to whatever was there, then restart it. That way, you don't have to worry about the actual value when you restart the timer.
 

Thread Starter

Art

Joined Sep 10, 2007
806
I was only looking at changing the least significant byte,
but it occurs to me now that even if you could decrement it in a single instruction,
it would have been incremented in the same instruction so you would drop two counts.

It does seem you’d have to stop, read it, and come up with a correct value to add for the time it took to do that.

I just tested my project at high frequency last night, and no error is introduced by me at 10 MHz.

 

jpanhalt

Joined Jan 18, 2008
11,087
It does seem you’d have to stop, read it, and come up with a correct value to add for the time it took to do that.
You do not have to stop TMR1 to read both bytes. Use the CCP peripheral in capture mode:

upload_2015-1-1_21-24-36.png

Presumably, you would just toggle the "event" from rising edge to falling edge (etc. ) and capture the 16-bit count between them. TMR1 can run continuously.

John
 

Thread Starter

Art

Joined Sep 10, 2007
806
Unfortunately the CCP1 pin is already used for hardware PWM to run the whole thing :D
It outputs 10 kHz PWM for the frequency dividers to come up with a bunch of other signals and a gate timer.

I shouldn’t need to know the values in TMR1 though, just modify one of them.
read -> increment or decrement -> write. It’s just a matter of whether or not the timer needs
to be stopped to do this.
There is a consideration that you’d want to avoid playing with it when it was too close to
overflow and was about to go to interrupt.


You do not have to stop TMR1 to read both bytes. Use the CCP peripheral in capture mode:

View attachment 78081

Presumably, you would just toggle the "event" from rising edge to falling edge (etc. ) and capture the 16-bit count between them. TMR1 can run continuously.

John
 

John P

Joined Oct 14, 2008
2,026
Yes, as I said, the capture input. But even if it were usable, I'm not sure it's what you want. Would it be OK to have this external input set a flag (could be an interrupt-on-change that you don't respond to) and then you'd test this in the interrupt, and if found, add or decrement the count for the next cycle? That's easy, but maybe you need to vary the timing for the current cycle, which sounds harder. One thing I'm doing on a current project involves a block of code that I want to have executed in proper sequence without interruption, but I don't wnt to suspend interrupts. So I'm checking the high byte of TMR1, and if it's 255 (i.e. timer is near wrapping around, and an interrupt is imminent) the critical block of code is bypassed, and executes later. Would something like that work for you?
 

Thread Starter

Art

Joined Sep 10, 2007
806
That might work since I’m trying to sync an external 1 second pulse to a 100 Hz pulse.
though Ideally the 1 pps would arrive while the ISR is being executed.
I still do have portb.0 ext interrupt pin free, but I suppose I’ve been avoiding problems associated with two events calling the ISR.

I had a hardware idea since I found out that when feeding the pic with a clock signal to clockin,
loading or tying high (I forget which one) the clockout pin stops the pic’s clock.
Perhaps I could invert the pic’s output signal in software, and match the pulse width of the GPS pulse,
then input both those signals to an AND gate, and use the AND gate output to stop the pic’s clock for the duration of the GPS pulse.

I can see this working in theory, and going to hell in practice perhaps. Maybe if it never stays synced,
the pic’s generated low time could be lengthened.

Yes, as I said, the capture input. But even if it were usable, I'm not sure it's what you want. Would it be OK to have this external input set a flag (could be an interrupt-on-change that you don't respond to) and then you'd test this in the interrupt, and if found, add or decrement the count for the next cycle? That's easy, but maybe you need to vary the timing for the current cycle, which sounds harder. One thing I'm doing on a current project involves a block of code that I want to have executed in proper sequence without interruption, but I don't wnt to suspend interrupts. So I'm checking the high byte of TMR1, and if it's 255 (i.e. timer is near wrapping around, and an interrupt is imminent) the critical block of code is bypassed, and executes later. Would something like that work for you?
 

John P

Joined Oct 14, 2008
2,026
I'm not sure that you saw the words "set a flag (could be an interrupt-on-change that you don't respond to)". What I meant was that you might (for example) send the external input to pin PortB.0, but you wouldn't enable the interrupt from that pin. What you'd do, in the timer interrupt, i.e the one interrupt that you do enable, would be to poll the flag that a transition on PortB.0 sets--that would be INTCON.1. And of course if the flag is found to be set, software must clear it. But you only need one interrupt to be enabled, not two.
 

Thread Starter

Art

Joined Sep 10, 2007
806
Oh ok sorry John, I saw the words, but didn’t understand the register would still be set if the interrupt for the pin was not enabled
(i.e. you didn’t have the register set to make port.0 interrupt jump to interrupt vector).

Well that being the case it’s the easier way especially because my back is more up to working on software than hardware at the moment,
so I’ll give it a go, and am confident, so thanks :)
Having said that, if it could be made reliable in hardware it would be down to dealing with clock cycles rather than instruction cycles!


I'm not sure that you saw the words "set a flag (could be an interrupt-on-change that you don't respond to)". What I meant was that you might (for example) send the external input to pin PortB.0, but you wouldn't enable the interrupt from that pin. What you'd do, in the timer interrupt, i.e the one interrupt that you do enable, would be to poll the flag that a transition on PortB.0 sets--that would be INTCON.1. And of course if the flag is found to be set, software must clear it. But you only need one interrupt to be enabled, not two.
 

NorthGuy

Joined Jun 28, 2014
611
I probably don't understand something, but the task you're trying to perform seems trivial.

To measure frequency: You calculate time between GPS pulses - giving X timer units. Then you calculate time between the pulses you want to measure - Y. The resulting frequency is F = Fgps*X/Y

To get time: You know the time at the momebt of the last GPS pulse. You simply add the time elapsed since then as measured by the timer (using the scale established by the distance between previous two GPS pulses).

Abandon the idea that the time has to be stored inside PIC's hardware timer. Instead, use the value of the timer and GPS info to calculate the time value at any given time.
 

Thread Starter

Art

Joined Sep 10, 2007
806
Hi, the clock is supposed to run independently of the GPS once it’s synced,
but I leave the GPS powered so it’s PPS output is still around to compare with.

So long as I haven’t unknowingly broken anything (and I don’t think so) I’ve completed it,
but still, the pic only has an instruction cycle every four clock cycles,
so depending when it was powered up, there could be four possible levels of accuracy that it sets to.

For example, if the pic is running at 10 MHz, 2.5 MHz instruction timing, you can’t do anything in software
to advance a clock by 1uS. It would take external hardware to make the clock frequency skip up to 3 cycles.

The yellow trace here is the GPS PPS signal, and the red trace, my PPS LED in the ISR.
I used some advice here and look at the portb.0 interrupt flag to reset the 100Hz ticks
from the ISR, and then have to add 83 counts to the timer1 low byte (just once).

 
Top