PIC16f877 Timer

Hi everyone,
I cant unerstand how the followin piece of code generates a pulse of 10 us please help....please give your comments

Note - assumes a 20MHz crystal, which is 5MHz timer clock
//A 1:4 prescaler is used to give a 1.25MHz timer count (0.8uS per tick)
//PIC16f877    

        TMR1H = 0xff;                                        // prepare timer for 10uS pulse
      TMR1L = -14;
      T1CON = 0x21;                                       // 1:4 prescale and running
      TMR1IF = 0;      
      trig = 1;                                           // start trigger pulse
      while(!TMR1IF);                    // wait 10uS
      trig = 0;                        // end trigger pulse
      TMR1ON = 0;                  // stop timer
vpoolAsked:
Who is Participating?
 
steveiamCommented:
Basic concepts:
 - The PIC's timers count upwards
 - Different timers have different sizes.  Some are 8 bit, some 16 bit.
 - The timer count speed depends on the processor's clock (e.g. 20 MHz), a built in scaling (/4), and a "prescaler" that you set (/1, /2, /4, ... /128).
 - When a timer gets to its maximum value (e.g. 65535 for a 16 bit counter), it then wraps around to 0, and sets the overflow flag (which is what you're testing with TMR1IF).

Going through your code one part at a time...

      TMR1H = 0xff;                                  // prepare timer for 10uS pulse
     TMR1L = -14;

These two lines set up the initial starting point for the timer to count upwards from.  Because the two variables are unsigned 8 bit integers, a bit of cleverness happens with the -14.  -14, represented in twos-complement is 0xF2.  That is then interpreted as an unsigned integer and put into TMR1L.  Basically, as the timer counts up, it'll take 14 counts to get back to 0 (and set the overflow flag).

Because the timer is a 16 bit value, there are actually two 8 bit bytes to it.. -H and -L.  Thus, the timer is really TM1H,TMR1L... 0xfff2, in this case.

     T1CON = 0x21;                                 // 1:4 prescale and running

The CPU has an external 20MHz clock (assuming you're not using the internal oscillator).  This frequency is then divided by 4, then by the prescaler (another 4).  This means that Timer1 ticks 20000000/4/4 = 1250000 times per second.

Since the timer is set to "14 counts", that's 1/1250000 * 14 = 11.2 microseconds

You're also turning the timer on, letting it start counting.

     TMR1IF = 0;    

This clears the timer overflow flag.  I'd suggest putting this before the line that starts the timer.

     trig = 1;                                    // start trigger pulse

Turn on an output pin (I know from your other questions that trig is defined as such).  I'd suggest putting this before the line that starts the timer.

     while(!TMR1IF);                 // wait 10uS

Wait for the flag to get set, i.e. when timer1 has counted from 0xfff2 up to 0.  From the calculation we did above, we know it'll be 11.2uS from when the T1CON = 0x21 line was executed.

     trig = 0;                    // end trigger pulse

Turn off the output pin.

     TMR1ON = 0;               // stop timer

Stop the timer from running.

I hope this helps explain what its doing!
0
 
PaulCaswellCommented:
Hi vpool,

I'd suggest you look here:

http://ww1.microchip.com/downloads/en/DeviceDoc/30292c.pdf

I am sorry but its much too hardware for me so I cant answer your question but I got to page 55 but my eyes started to glaze over at that point.  

Paul

By the way, this question might be better off in the 'Assember' page here at EE? I can move it there if you like. Just post here and I'll move it.
0
 
basicinstinctCommented:
Hi there - this is my understanding of the code, although I have never used this chip:

The pulse is started here:
 trig = 1;                                    // start trigger pulse

Now the timer starts incremeneting its count every clock cycle.  The while loop below says "loop while TMR1 has not reached 31" - because the loop body contains no code there are no instructions to execute, it just keeps looping.

while(!TMR1IF);                 // wait 10uS

When TMR1 reaches 31 the loop ends and the pulse is ended with this line:

trig = 0;                    // end trigger pulse


The fact that 31 clock cycles = 10uS simply reflects the clock speed (and you have to factor in the prescale setting which determines how much the timer is incremented per clock cycle).  If the clock went twice as fast the same code would give a 5uS pulse.  If the clock was half as fast the same code would give a 20uS pulse.
0
 
steveiamCommented:
A couple of comments on basicinstinct's answer..

> while(!TMR1IF);                 // wait 10uS
> When TMR1 reaches 31 the loop ends and the pulse is ended with this line:

Not sure where you're getting your 31 from!

This while loop is watching the TMR1 overflow flag.  When the overflow happens, its set to 0, and then exits the while loop.  You aren't actually watching the value in the timer itself, but the flag it sets when the timer has counted all the way up to its maximum, and rolled over to 0.

> The fact that 31 clock cycles = 10uS simply reflects the clock speed
> (and you have to factor in the prescale setting which determines how
> much the timer is incremented per clock cycle)

This is partly right.  However, the timer is always incremented by one, every time it is incremented.  The prescaler (elsewhere in the code) sets how fast the increments happen.  The load value for the timer (-14) is not clock cycles.

It is correct, though, that the speed of the timer is dependant on the clock speed of the chip... either the external oscillator that you use, or the internal oscillator.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.