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 CCS Technical Support

Timer1 help

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



Joined: 05 Jan 2006
Posts: 105

View user's profile Send private message

Timer1 help
PostPosted: Sun Jul 27, 2008 12:44 pm     Reply with quote

hello every body
i need timer1 to overflow every 1 second, how can i do that? i search but i cant find clear way to decide the value in set_Timer1(0xvalue)
any body can help me and explain, please?

note that i use 16f877a with 4Mhz osc
here is my code:
Code:

#include<16f877A.h>
#fuses NOWDT, XT, NOPROTECT
#use delay (clock=4000000)
#priority timer1,ext
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

long x;

#INT_EXT
void ext_isr() {
   x++;
}


#INT_TIMER1
void timer1_isr() {

   delay_us(1);
   printf("X:%lu\r\n",x);
}


int main()
{
         x=0;

         set_timer1(0x0000); // this must changed to match overflow every //1000ms
         setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);

         enable_interrupts(GLOBAL);
         enable_interrupts(INT_EXT);
         enable_interrupts(INT_TIMER1);

         ext_int_edge( H_TO_L );

     while (1)   {}


          }//main


thank you
Ttelmah
Guest







PostPosted: Mon Jul 28, 2008 10:37 am     Reply with quote

What you show, won't work.
Think of the timer, a bit like a strange game of 'snakes and ladders'. The height of the ladder, is set by the size of the timer (256 rungs, or 65536 rungs, for 8bit, or 16bit timers). You step 'up' the ladder, at the programmed clock rate. Normally the master oscillator/4, over any 'prescaler' value, available to the timer. So, for timer1, with a 4MHz clock, you can climb at 1 rung every uSec, or 2uSec, 4uSec, or 8uSec.
Then when you get to the top of the ladder, the interrupt occurs,and you fall straight back to the bottom of the ladder.
'Setting' the timer to a value, jumps you _once_, to a particular rung. However when you get to the top, you again fall back to the bottom of the whole ladder.
One 'solution', then is to set the 'rung' in the interrupt. Unfortunately, the counter is running all the time, and it takes _time_ to get into the interrupt code. If you set a particular count, and one or more counts has already occurred, these get lost, and the accuracy vanishes. Even if you set the rung, to the current count + the required 'jump', there will be errors if the count increments between reading, and writing...
Now, look at values. Work in uSec. There are 1000000 in one second. The counter counts up to 65536. Multiply 65536, by the largest prescaler (8). 524288. Less than the million you need. So, this timer, _cannot_ count one second.
In fact, none of the timers on your chip, can go this long on the standard clock. You either have to use a lower frequency clock feeding the chip/timer, or use a faster timer 'tick', and count these.
Now, the one timer that is different in this, is timer2. This is a bit like an 'extension ladder', and you can actually change it's effective 'length', allowing it to automatically count to particular numbers and reset.
If (for instance), you set this up with:

setup_timer2(10,249,10);

Then it will run off the master oscillator/40 (/4 /10 - the first 'prescaler'), divide this by 250 (second number+1), and then only interrupt on the tenth time round (third number). 40 times per second.
Then in the timer interrupt, have:
Code:

#INT_TIMER2
void tick(void) {
   static int counts=39;
   if (counts) --counts;
   else {
       counts=39;
       //do your 1/second job here
   }
}


This gives a system 'tick', running 40*per second, which you then use to generate the one second counter.

Best Wishes
hadeelqasaimeh



Joined: 05 Jan 2006
Posts: 105

View user's profile Send private message

PostPosted: Tue Jul 29, 2008 6:20 am     Reply with quote

hi Ttelmah
i think i got the idea,and i use Timer2 as you post,but still not working!
maybe there is some misunderstanding, Crying or Very sad here is the code:
Code:

#include<16f877A.h>
#fuses NOWDT, XT, NOPROTECT
#use delay (clock=4000000)
#priority timer2,ext
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

int1 flag;
long x;

#INT_EXT
void ext_isr() {
   x++;
}

#INT_TIMER2
void tick(void) {
   static int counts=39;
   if (counts) --counts;
   else {
       counts=39;
       //do your 1/second job here
       printf("X:%lu",x);
   }
}




int main()
{
         x=0;
         setup_timer_2(10,249,10);
         set_timer2(0);
         enable_interrupts(GLOBAL);
         enable_interrupts(INT_EXT);
         enable_interrupts(INT_TIMER2);

         ext_int_edge( L_TO_H );

     while (1)   {

     }


          }//main



i wonder what this line do:
Code:

         set_timer2(0);


thank you very much
ckielstra



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

View user's profile Send private message

PostPosted: Thu Jul 31, 2008 6:29 pm     Reply with quote

hadeelqasaimeh wrote:
i wonder what this line do:
Code:

         set_timer2(0);
If you don't know what the line does, why did you put it in?
This line sets the value of timer2 to a known start-up value. Good coding practice but pointless because the time of your application start-up is unknown so who cares if the first timer interrupt occurs a few milliseconds sooner or later.
Keep the line if you like a strict programming style. Or remove the line if you want to save a few bytes memory (my preference).

Code:
setup_timer_2(10,249,10);
The calculation is correct but doesn't match the hardware capabilities. Check the datasheet for the prescaler options of this chip and you will find: 1, 4 or 16.
Many possible setup combinations can be used to create a 1s counter but for optimal performance you want to minimize the interrupt overhead. Configure timer 2 to generate as few interrupts as possible and still get a nice integer value for the counter in the interrupt handler.

For example: setup_timer_2(T2_DIV_BY_16, 249, 10) and in the interrupt count to 25.
16 * (249+1) * 10 * 25 = 1,000,000
1MHz * 4 clocks per count (always) = 4MHz

Edit 4-Aug-2008: fixed a stupid bug in the prescaler setting. Now use the defined value T2_DIV_BY_16 instead of a hardcoded value.
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