CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Timer2 easy question

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

Timer2 easy question
PostPosted: Fri May 19, 2006 5:45 am     Reply with quote

Hello,

I want to interrupt every 10ms using timer2. Now I've used the search function of the forum. That brought me to this implementation:

Using a 4 Mhz ceramic resonator:

#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#use delay(clock=4000000)

start the timer:

Code:
setup_timer_2 (T2_DIV_BY_4, 249 , 10); // Timer2 Interrupt


Timer2 isr:

Code:
#int_Timer2
Timer2_isr()

   TIMER2_ITR = TRUE;
}// TIMER2


in main: check flag and do the required

Code:
//******************** TIMER2 interrupt vlag afhandelen **********************//
   if (TIMER2_ITR)
   {
      TIMER2_ITR = FALSE;     
// De batterijspanning wordt gemeten elke minuut en zowieso doorgestuurd.
      teller++;
      if (teller == 1000)  // 1000 * 10ms = 10s
      {
         Meet_Vbat(&Vbat);       // Vbat meten
         if (!E3_SLEEP)          // Stuur de batterijspanning door naar E3 als deze
         {                       // niet in sleep staat
            Send_Vbat(Vbat);
         }
      teller = 0;
      }     
}


So what _should_ happen is that battery voltage is sent to the serial port every 10 seconds. Now it does send it but every 21 a 22 seconds and I don't understand why. Who helps me with this timing?
Timing is not critical. Has to be approximately 10 seconds.



Code:
drh



Joined: 12 Jul 2004
Posts: 192
Location: Hemet, California USA

View user's profile Send private message

PostPosted: Fri May 19, 2006 8:15 am     Reply with quote

According to your code, there are 2 conditions that determine when you send the battery voltage. One of them is if "teller" is equal to zero. The other is if "E3_SLEEP" is false. If you are sure that the timer is functioning correctly, what's connected to E3_SLEEP? And is it in the correct state?
_________________
David
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Fri May 19, 2006 8:21 am     Reply with quote

Drh
E3_SLEEP is set to FALSE; always.
There's something wrong with the timer. I want it to send at 10 seconds
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri May 19, 2006 8:26 am     Reply with quote

Try this:

Code:
setup_timer_2 (T2_DIV_BY_16, 249 , 10); // Timer2 Interrupt


This will have the timer ISR being entered 25 times a second.

Code:
#int_Timer2
Timer2_isr()

   if(++counter > 24)// when the counter reaches 25
   {
      counter = 0;
      if(++counter2 > 9)// this will enter every ten seconds
      {
        counter2 = 0;
        TIMER2_ITR = TRUE;
      }
   }
}// TIMER2


This ISR will make TIMER2_ITR go true every ten seconds. Then, in your main body, you can evaluate that and do whatever you need to do.

I do this quite a bit when I need to have something happen at a certain frequency.

Ronald
Ttelmah
Guest







PostPosted: Fri May 19, 2006 8:46 am     Reply with quote

I'd actually do this a slightly different way.
Though I am always preaching 'keep the interrupt handler short', the work involved in a simple test and/or subtraction, is only a couple of machine cycles. So:
Code:

int16 tick;

#int_Timer2
Timer2_isr()  { 
   if (tick) --tick;
} // TIMER2


Then in main:
Code:

if (tick==0) {
   tick=1000;
   Meet_Vbat(&Vbat);
   if (!E3_SLEEP)
       Send_Vbat(Vbat);
}


The advantage of this, is that it makes it impossible for main to 'miss' the countdown. Testing for a value 'equal to', has the problem that if something occurs and the main code doesn't get to the test on that loop, it can be skipped...
Note also that resetting the tick, is the first thing done. Otherwise if the printout takes any significant time, a count may be missed.
If your main loop is taking more than 10mSec to go 'round', then this may be the cause of the problem, with the count only updating at half the interrupt frequency.
If this doesn't fix it, then I have to agree with the possibility that it is 'E3_SLEEP' causing the problem. Try with this removed.

Best Wishes
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Fri May 19, 2006 9:22 am     Reply with quote

At first thanks for the input.

Quote:
If your main loop is taking more than 10mSec to go 'round', then this may be the cause of the problem, with the count only updating at half the interrupt frequency.


I'm sure this is the problem.

Here 's my new implementation:

Timer2 isr:

Code:
#int_Timer2
Timer2_isr()
{       
   teller++;
   if (teller == 6000)
   {
      ONE_MINUTE = TRUE;
      teller = 0;
   }  // 6000 * 10ms = 01m00s

   if (Debounce_counter == 0)
   {
      if (On_off_State == input(AAN_UIT))
      {
         BUTTON_DEBOUNCED = TRUE; 
      }
      Debounce_Counter = 255; // 255 is a special value that means that no debouncing is happening
   } // If debounce nodig

   else if (Debounce_Counter < 255)   
   {
      --Debounce_Counter;
   }
}// TIMER2


in main flag resetter and handler:

Code:
//***************************** ONE MINUTE Teller ****************************//
// De batterijspanning wordt gemeten elke minuut en zowieso doorgestuurd.
   If ( ONE_MINUTE )
   {     
      ONE_MINUTE = FALSE;
      Meet_Vbat();       // Vbat meten
      if (!E3_SLEEP)          // Stuur de batterijspanning door naar E3 als deze
      {                       // niet in sleep staat
         Send_Vbat(Vbat);
      }
   }


Off course I'll try the 'tick' implementation. But that will be on monday. Have a nice weekend.
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Thu Jun 22, 2006 3:39 am     Reply with quote

About

Code:
setup_timer_2 (T2_DIV_BY_4, 0xF9 , 10); // Timer2 Interrupt elke 10mS


How can I adapt that code in order to interrupt every 20 ms ?
Is that:

Code:
setup_timer_2 (T2_DIV_BY_4, 0xF9 , 20); // Timer2 Interrupt elke 20mS


?
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Thu Jun 22, 2006 6:14 am     Reply with quote

Quote:
Depends whether your chip has it!. You don't mention what the chip is. Data sheet...
MicroChip, have an application note about the various timers.
The 'point' about timer2, is that it has a hardware circuit to 'reset' it at a specified count. It can also interrupt on every 'n' counts (where 'n' is a 4 bit counter). So if your chip has it:

setup_timer2(T2_DIV_BY_4,249,10);

Will for a 4MHz clock, divide this by 16 (/4, then /4 in the prescaler), count from 0...249, and interrupt every tenth time through the count, giving an interrupt every 10mSec. Rather nice for timing. :-)
Be careful about the counter value. The 'wizard', gets this wrong, as does the help file. the chip counts from zero _to_ the value specified, and resets on the _next_ cycle. Hence for 250 counts, you need 249, yet the wizard insists on using 250. The MicroChip notes have this right As you'd - hopefully - expect!).

Best Wishes


I found this as an explanation, but don't really understand that in order to get a 20 mS interrupt..

I think:

Code:
setup_timer2 (T2_DIV_BY_8,249,10);   //20 MS itr
Ttelmah
Guest







PostPosted: Thu Jun 22, 2006 8:43 am     Reply with quote

Yes.
The formula, is:

(((Clock/4)/prescaler)/(max count +1))/postscaler

counts per second.

So for 20mSec = 50 counts per second, you need:

prescaler * (max count+1) * postscaler = (4000000/4)/50

8 * (249+1) * 10 = 20000

Spot on.

Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Jun 22, 2006 8:47 am     Reply with quote

You didn't mention the processor you are using, but Timer2 operates similar in most PIC models. For the next explanation I suggest you study the diagram for Timer2 in your datasheet.

Your processor has a clock crystal of 4MHz. By design the PIC processors are executing instructions at a frequency that is a factor 4 slower than the clock frequency, in the datasheets this is named Fosc/4. This same clock is also the base frequency for the timers, in your situation this means 1 million counts per second.

You want to get an interrupt every 20ms, i.e.:
= every 0.02 seconds * 1 million counts
= every 20,000 counts

20,000 is too large to fit in the 8 bits counter of Timer2. Now you can decide to use either one of the larger 16-bit timers or you can use the post- and prescalers to make it fit in an 8-bit counter.

Since you decided on using Timer2 you will have to find a combination of post- and prescalers settings that equals 20,000.
Assuming you have a PIC18F458 you have the following possible settings:
Prescaler: 1, 4 or 16
Postscaler: 1 to 16
Period register (PR2): 0 to 255
Now with some simple arithmetic you can find combinations that work, for example:
prescaler 16 * postscaler 5 * PR 250 = 20,000
prescaler 16 * postscaler 10 * PR 125 = 20,000

Quote:
I found this as an explanation, but don't really understand that in order to get a 20 mS interrupt..

I think:

Code:

setup_timer2 (T2_DIV_BY_8,249,10);   //20 MS itr
8 * (249 + 1) * 10 = 20,000
This would be a valid setup, only too bad that T2_DIV_BY_8 is not supported for Timer2.

Always have the datasheet of your PIC processor at hand. Programming a microcontroller is 'close' to the hardware, so please study the datasheets carefully.
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Thu Jun 22, 2006 9:13 am     Reply with quote

Thks for the input, guys.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group