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

BUG ? delay_ms() function in ISR
Goto page Previous  1, 2, 3
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kender



Joined: 09 Aug 2004
Posts: 768
Location: Silicon Valley

View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger

PostPosted: Mon May 22, 2006 6:11 am     Reply with quote

Christophe wrote:
It has to be initialised to 100. Where is that done? the article says it's initialised 0.

Static variable is initialized during declaration (like const variables).

Code:
static int8 iCount = 100;
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Mon May 22, 2006 6:32 am     Reply with quote

Here's my off_timer implementation. However I think I'm doing double work at couting seconds / minutes. Feel free to comment or correct.

Timer2 isr()
Code:
//************************** Timer2 interrupt ********************************//
//Timer0 overloopt elke 10 ms.
#int_Timer2
Timer2_isr()
{
static int8 Count = 100;
// counting minutes and hours if TRUE
   if ( OFF_TIMER_ENABLED )
   {
      if ( (--Count) == 0)
      {
         Count = 100;
         secs++;            //Do your seconds update here

         if (secs == 60)
         {
            mins++;
            secs = 0;
         }
         if (mins == 60)
         {
            hrs++;
            mins = 0;
         }
// Na x tijd de ES uitschakelen om energie te sparen
         if ((mins == off_mins) && (hrs == off_hours))
         {
            OFF_TIMER_AFGELOPEN = TRUE;
            OFF_TIMER_ENABLED = FALSE;

         }
      } // 1 seconde
   } // OFF_TIMER_ENABLED
     
   if (teller)
      --teller;
   
   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():

Code:
//*********************** On / Off switch event Handler **********************//
   if (BUTTON_DEBOUNCED)
   {
      BUTTON_DEBOUNCED = FALSE;
 // Na 3 interrupts = 32.8ms wordt de debounce routine gestart.
         if (input(AAN_UIT))  // switch naar boven: RB0 = 3V
         {
           // if (E3_OFF)
           // {
           //    BOOT_E3();
           // }
            for (k = 0; k < 20 ;k++)
            {
               putc(0);
            }
            printf("%c%S%c", COMMANDO_BYTE, WAKE_COMMANDO,0);
            ext_int_edge(H_TO_L);   // Volgende EXT_ISR() is bij overgang L 2 H
         }
         else                 // switch naar beneden
         {
            if (SPACE_PRESSED)
            {
               SPACE_PRESSED_WHILE_SHDN = TRUE;
            }
            printf("%c%c%S%c",0 ,COMMANDO_BYTE, SLEEP_COMMANDO,0);
            ext_int_edge(L_TO_H);
         }
   }

//***************************** ONE MINUTE Teller ****************************//
// De batterijspanning wordt gemeten elke minuut en zowieso doorgestuurd.
   if (teller == 0)
   {
      teller = 6000;
      Meet_Vbat();
      if (!E3_SLEEP)
         Send_Vbat();
   }
 
//*************** TIMER1 OFFTIMER afgelopen vlag afhandelen ******************//
   If (OFF_TIMER_AFGELOPEN)
   {
      SETUP_TIMER_1(T1_DISABLED);
      OFF_TIMER_AFGELOPEN = FALSE;

      putc(mins);
      BUZZER();
      delay_ms(400);
      BUZZER();
      // TOGGLE_E3();
   }


This is where the OFF_TIMER gets started or halted by setting or resetting a flag:

Code:
case OFF_TIMER:
                           if ( data[ (write_pointer + 6)%BUFFER_SIZE]  <= 120)
                           {
                              off_mins = (data[ (write_pointer + 6)%BUFFER_SIZE] * 6) % 60;
                              off_hours = (data[ (write_pointer + 6)%BUFFER_SIZE] * 6) / 60;
                              //off_mins = 1;
                              //off_hours = 0;
                           }
                           else
                           {
                              off_mins = 0;
                              off_hours = ( data[ (write_pointer + 6)%BUFFER_SIZE ] - 200 ) * 24;
                           }
                           // Timer1 stopzetten
                           if ( off_mins == 0 && off_hours == 0)
                           {
                              OFF_TIMER_ENABLED = FALSE;
                           }
                           // Timer1 starten
                           else
                           {
                              secs = 0;
                              mins = 0;
                              hrs = 0;
                              OFF_TIMER_ENABLED = TRUE;
                              //setup_timer_1( T1_INTERNAL | T1_DIV_BY_8 );
                              //Set_timer1 ( 3035 ); // Start de Timer1 vanaf 3035
                           }
                           break;
Ttelmah
Guest







PostPosted: Mon May 22, 2006 6:42 am     Reply with quote

Christophe wrote:
It has to be initialised to 100. Where is that done? the article says it's initialised 0.

It doesn't have to be initialised to 100.
If you wan't to, then just set it to the value in the declaration.
However I was being 'cheeky', and just letting it decrement 'round' to 0, and then be re-initialised. This means there will be a pause during boot while the clock doesn't run, which in some circumstances, can be 'useful'. It is up to you.

Best Wishes
Ttelmah
Guest







PostPosted: Mon May 22, 2006 7:03 am     Reply with quote

The only 'extra' work, is the decrement and test of 'count', in 99 out of 100 calls. Only in the 100th call, is the 'seconds' incremented. Similarly, only in 1/6000 calls, is the minutes incremented.
Now notice that I used a decrement, rather than an increment. The reason for this, is that when you execute a 'decrement' instruction, the 'zero' flag gets set if the result is 0. The chip contains a 'decrement and skip' instruction, which decrements a byte, and tests all in one instruction (two instruction times, since it is a 'double byte' instruction). If you do an increment and compare instead, you have to perform an increment, and then a seperate comparison, which doubles the time actually taken (tiny amount but worth saving).
So using the decrement version, in 99 out of 100 loops, involves just four extra instruction times. The actual 'seconds/minutes' code is exactly the same as what was already being called, and is called at the same frequency.
What you 'lose', is about the same as the saving, since calling any interrupt, has quite a large overhead associated with it, which you don't see. There are something in the order of 70 extra instruction times hidden 'behind' any interrupt on a 18 chip (just fractionally less on a 16 chip). The big plus though, is that you are then developing 'time' based on a hardware counter, rather than something that is dependant on a software timing (how long it takes to reach the point where you adjust the timer count). Hardware rules!...
It is well worthwhile, getting your head 'round', how different timings can be for different C instructions. For instance, on a 4MHz chip, an instruction like:

count++;

With 'count' as an integer, takes just 3uSec, including fetching and saving the value. However the very similar:

count++;

With 'count' as a floating point value, takes 556uSec!. You can write a C 'one liner', that can take seconds to execute (printf, with some floating point values and arithmetic), conversely a statement that appears as long, can in some cases be executed in a few uSec. Knowing where the bottlenecks are, is the hard part!.

Best Wishes
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Mon May 22, 2006 7:31 am     Reply with quote

Thanks for the input. I understand that there is few extra work.

Now in one timer2() I am doing:

* counting minutes using int16 teller.
* couting 30 mS delay time to debounce an on off switch.
* couting seconds / minutes / hours when a flag is set.

Now is there a way to combine this all? As I am doing 3x the same. Is there a shorter way to do this all? Off course it works perfectly, this code.
Ttelmah
Guest







PostPosted: Mon May 22, 2006 7:59 am     Reply with quote

Most of these things are not actually happening!...
What happens, in the normal interrupt is:

Decrement one counter.
Is it zero?.
No.
Is the flag set to do a debounce?.
No.
Exit.

Total of only perhaps a dozen instructions.

Even on the occassions when the flags are set, the extra code is tiny. This is the point I was trying to make. You have to look at the best, and worst case total times. In this case, only perhaps 50 instructions 'worst case', and this will happen very rarely.

The only place you could 'save', is if you combine the minute counters, but the amount of code here is tiny.

Best Wishes
newguy



Joined: 24 Jun 2004
Posts: 1899

View user's profile Send private message

PostPosted: Mon May 22, 2006 10:39 am     Reply with quote

Christophe wrote:
Newguy,

are you perhaps a school teacher? Many thanks for the clear explanation. Now I understand interrupts and handling them a lot better. Guess almost everything about interrupts and keeping them short was tackled there.


Ding ding ding. You guessed right. Used to teach electrical engineering in university. I amassed a long list of mental tricks/analogies during that time. Glad you found this one helpful.
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Tue May 23, 2006 1:07 am     Reply with quote

Ttelmah wrote:
Most of these things are not actually happening!...
What happens, in the normal interrupt is:

Decrement one counter.
Is it zero?.
No.
Is the flag set to do a debounce?.
No.
Exit.

Total of only perhaps a dozen instructions.

Even on the occassions when the flags are set, the extra code is tiny. This is the point I was trying to make. You have to look at the best, and worst case total times. In this case, only perhaps 50 instructions 'worst case', and this will happen very rarely.

The only place you could 'save', is if you combine the minute counters, but the amount of code here is tiny.

Best Wishes


So we are using only 1 timer for different applications.
Now my question is? In what case/when should you use another timer? It seems that you can use only 1 timer for many applications as this example states.
Ttelmah
Guest







PostPosted: Tue May 23, 2006 2:39 am     Reply with quote

Obvious answer would be 'when you need to time different things'. :-)
The 'timers', are really not 'timers', but counter/timers, and can be fed from the processor clock, or external sources. Some 'classic' examples of alternative uses, would be:
1) Run one timer from a 32KHz crystal, while running the CPU, from an 'innaccurate' source like the internal RC oscillator. This timer can then stay running, at low power, to wake the processor from sleep at a defined interval, and provide an accurate 'time'.
2) Run one timer at a much higher rate, as the source for a PWM. So you perhaps have a system 'tick' timer at 50Hz, and a PWM, at 50KHz.
3) Use timers as counters for external events. So you could count how many pulses of an external signal occur in a 'known' time from another timer. Gives frequency measurement.
4) Use a counter, so that you know how many cycles of the internal clock, occur between specified external events. This is the 'inverse' of the one above, giving measurement of 'period'.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3
Page 3 of 3

 
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