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

Timers

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



Joined: 30 Dec 2011
Posts: 20
Location: UK

View user's profile Send private message

Timers
PostPosted: Tue Jan 24, 2012 2:28 pm     Reply with quote

Hello once again. I wonder, am I able to use different timers for different tasks in a project or am I restricted to one? If yes, do I declare the other timer(s) at start of code or within the concerned blocks? Within these blocks do I specify which timer to use such as

delay_timer_0( 100)?

My code executes PWM and other functions which need different time delays. I'm looking at the many forum posts but I don't seem to find a pointer.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Multiple timers
PostPosted: Tue Jan 24, 2012 4:22 pm     Reply with quote

I'm not too sure exactly what it is you're after. The simple answer is yes, you can use different timers for separate tasks. Unless you clock a timer from an external source all the internal timers in a PIC run at essentially the same rate since they're clocked by the same crystal. The pre and post scalers will give you a wide range of time intervals.

You can get loads of different timers to work from one source.

Here's one way of doing it for ms delays :-

I avoid using constructs of the delay_ms() variety. I use one of the PIC timers to generate an interrupt at 1ms intervals (i.e. a 1ms tick). I have as many task timers as needed, task_1_timer, task_2_timer......... In the ISR, all the timers are decremented and either set a flag or are clamped when they reach zero. When a delay is needed, main() sets task_n_timer to the required delay, it is then polled, along with the others, until main() detects that the required time has passed, job done. In this way each timer is independent of the others except that they all clock at the same time.

Mike
chrismdube



Joined: 30 Dec 2011
Posts: 20
Location: UK

View user's profile Send private message

timers
PostPosted: Tue Jan 24, 2012 5:57 pm     Reply with quote

Thanks for your reply Mike. I can't say I understood though. If you don't mind can I have a sample code please. These ISRs make my heard spin. I have a book here but it doesn't help much.
I am trying to separate my sequences from the PWM timer, that's why I need at least another independent timer. Even a reference to read would be much appreciated.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Tue Jan 24, 2012 6:18 pm     Reply with quote

My apologies to whomever I stole this from, but this is a good example of how to run many software timers in a program:

Your approach will work, but I would make it into a more general solution because you are likely to have a wish for more timers. What I often do is to create a timer interrupt that is always running and triggered every 100ms, then inside this interrupt I create as many 'Software Timers' as I want. These timers work by the main routine setting a value, and then in the interrupt the value is decremented every 100ms until it reaches zero where it stops. In main I will test for the timer to have reached zero and then perform the timer based action and/or set a new value.

Example:
Code:

//-------------------------------------------------------------
// Timer0 interrupt, triggers every 100 miliseconds.
// Used for multiple software based timers.
//-------------------------------------------------------------
#int_timer0
void timer0_isr()
{
  // Many software count down timers...
  if (GprsStateTimer)     GprsStateTimer--;
  if (LocalTimer)         LocalTimer--;       // General purpose timer for temporary local use
  if (SignOfLiveTimer)    SignOfLiveTimer--;
  if (GprsTxDelayTimer)   GprsTxDelayTimer--;
 
  if (LedOnTimer)
  {
    LedOnTimer--;           // Count down till 0
    if (!LedOnTimer)        // Switch LED off on time out.
      output_low(LED);
  }

Now, if in the Main routine I need to do some processing where a maximum timeout is defined I can do it like this:
Code:

#define TIMER_EXPIRED   0     // Value of the software timers when expired.

  // Initialize MMC memory card
  LocalTimer = 5;     // According to the MMC specs a max. of 500ms.
  do
  {
    Result = MMC_SendCmd(SEND_OP_COND);
  }
  while ((Result != R1_OK) && (LocalTimer != TIMER_EXPIRED));

The LED timer was a piece of code where I needed a LED to be on for a defined moment of time. So in the main routine I would set:
Code:

    output_high(LED);
    LedOnTimer = ONE_SECOND;   // Switch LED off after 1000ms

And then the main program would continue with the interrupt routine taking care of the LED to switch of after 1 second.

The main difference with your approach is that I never enable/disable the timer interrupt allowing for many software timers into this single hardware timer. You only have to disable/enable the timer interrupt when the counter variable is larger than an int8, then the action of setting the value will no longer be an atomic operation (a single assembly instruction).
_________________
The search for better is endless. Instead simply find very good and get the job done.
chrismdube



Joined: 30 Dec 2011
Posts: 20
Location: UK

View user's profile Send private message

timers
PostPosted: Tue Jan 24, 2012 6:49 pm     Reply with quote

Wow! This is too much to take on first feet. Thanks again guys but isn't there a way I could use the hardware timers without getting too deep. Confused
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Multiple timers
PostPosted: Wed Jan 25, 2012 7:45 am     Reply with quote

You asked.
Quote:

I wonder, am I able to use different timers for different tasks in a project or am I restricted to one?


What kind of delay software do you have in mind?

In the CCS examples you will find software of the delay_ms() variety. The big problem is that you can only run one of these delays at a time since each of them grabs all the processor time. What SherpaDoug and I are offering is a means to use either one (or more) of the hardware timers to achieve multiple effectively simultaneous timers. If you use different hardware timers for each function you will very rapidly run out of resources.

To SherpaDoug

I do not disable my timer, it simply runs continuously. The main difference between my approach and yours is that I have more of the action in main(). You start your timer in main() and end it in the ISR. I have start and stop actions in main(). Our systems are very similar.

For chrismdube's benefit, here's a short complete compilable for a PIC16F877A. The program flashes LEDs on RB0 & RB1 at slightly different rates around 2Hz. The LEDs start in step then flash in and out of step with each other every 13s.

Code:


#include <18F458.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK) 

 signed int16   rb0_led_timer;            //
 signed int16   rb1_led_timer;

void main()
{
   setup_timer_2(T2_DIV_BY_4, 249, 1);      // Generates 1ms tick
   enable_interrupts(int_timer2);
   enable_interrupts(global);


   rb0_led_timer = rb1_led_timer = 0;      // clears timers
   output_high(pin_b0);                  // forces defined state
   output_high(pin_b1);                  //   "

  while( TRUE )
 {
   if (rb0_led_timer<=0)         // Tests for time out
   {   rb0_led_timer = 250;       // Restarts timer
      if (input(pin_b0))         // Test b0
      { output_low(pin_b0); }      // Clears if set
      else
      { output_high(pin_b0);}      // Sets if clear
   }

   if (rb1_led_timer<=0)         // Tests for time out
   {   rb1_led_timer = 260;       // Restarts timer
      if (input(pin_b1))         // Tests state of b1
      { output_low(pin_b1); }      // Clears if set
      else
      { output_high(pin_b1);}      // Sets if clear
   }
 }
}

#int_timer2
void update_timers()
{
   rb0_led_timer--;
   rb1_led_timer--;
}


If you make the timer intervals quite short (say 2ms & 3ms respectively) you can watch the action on your oscilloscope. The whole thing then repeats every 12ms.

Mike


Last edited by Mike Walne on Sat Jan 28, 2012 4:27 am; edited 2 times in total
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Separate hardware timers
PostPosted: Wed Jan 25, 2012 4:45 pm     Reply with quote

Quote:

Wow! This is too much to take on first feet. Thanks again guys but isn't there a way I could use the hardware timers without getting too deep

Yes, you can use something based on either SherpaDoug's or my method. You will gain most by doing most of the work yourself. I think we have given you enough.

Mike
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