|
|
View previous topic :: View next topic |
Author |
Message |
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
|
Posted: Mon May 22, 2006 6:11 am |
|
|
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
|
|
Posted: Mon May 22, 2006 6:32 am |
|
|
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
|
|
Posted: Mon May 22, 2006 6:42 am |
|
|
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
|
|
Posted: Mon May 22, 2006 7:03 am |
|
|
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
|
|
Posted: Mon May 22, 2006 7:31 am |
|
|
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
|
|
Posted: Mon May 22, 2006 7:59 am |
|
|
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: 1900
|
|
Posted: Mon May 22, 2006 10:39 am |
|
|
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
|
|
Posted: Tue May 23, 2006 1:07 am |
|
|
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
|
|
Posted: Tue May 23, 2006 2:39 am |
|
|
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 |
|
|
|
|
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
|