![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
kamillas
Joined: 24 Oct 2011 Posts: 50
|
Timer0 interrupt |
Posted: Fri Nov 11, 2011 7:21 am |
|
|
I want to understand the operating principle of Timer0, so I made a program for powered two LEDs. I want to be fed LED1, and after a delay of 1s LED2 lights, and after that my program return to the interruption to supply the LED1. Help me in this program
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=4000000)
#int_timer0
void TIMER0_isr()
{
output_high(PIN_b0);
delay_ms(500);
}
void main(void)
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
while(1) {
output_high(PIN_B7) ;
delay_ms(500);
output_low(PIN_B7);
;
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Fri Nov 11, 2011 9:06 am |
|
|
First the is almost never ever a good reason to have a delay_ms in an interrupt routine most especially a time ISR.
The best thing to do is to look at the CCS examples that create a 1 sec tick. Most often in the timer ISR you set up a tick rate. Then you count the ticks. When the ticks reach the delay time you wish you start the tick count over. Think of the timer and its ISR as a clock separate to your main code. The tick count itself or a flag is passed as a global to your main routine. In your main routine your code does other things including checking on the tick count flag. The golden rule with ISR's is put as little little little code in them as you possibly can. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Fri Nov 11, 2011 9:17 am |
|
|
Key reason this won't do what you want, is using the delay in the interrupt.
The compiler will be giving you a warning here.
Problem is that the chip does not support 're-entrant code'. This is where you call a routine from inside itself (basically very difficult to implement, unless the chip has a variable stack, which the PIC does not.....).
Now, because you also have a delay called in the external 'main' code, interrupts _will_ be disabled for the entire 500mSec while this executes, to prevent the second delay from being called....
Now, it is not really clear from your description, or code, what you actually want to happen. But consider something like:
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT,HS,PUT,NOPROTECT,NODEBUG
#FUSES NOBROWNOUT,NOLVP,NOCPD,NOWRT
//General comment here, PUT is much safer, unless you are really _sure_
//How fast your supply rail, and oscillator startup...
#use delay(clock=4000000)
int1 clock1=0,clock2=0;
#int_timer0
void timer0_isr(void) {
if (clock1) --clock1;
if (clock2) --clock2;
}
void main(void) {
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_64);
//Tick approx 60* per second
clock2=15;
output_low(PIN_B7);
output_low(PIN_B0); //Assuming low=off
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
do {
if (clock1==0) {
output_toggle(PIN_B7) ;
clock1=30;
}
if (clock2==0) {
output_toggle(PIN_B0);
clock2=30;
}
}
}
|
Now here, the LED's are all switched in the main code, based on clocks. You will have to set them how you want, but currently, B7 will toggle about every half second, and B0 will toggle 1/4 second out of phase with this. You can run the LED's at different speeds by just changing the count you load into clock1/clock2.
Obviously by changing the clock speed, and counts used, you can change the LED's at any time you want. Similarly, by starting with one on, instead of off, you can reverse the phase.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
SSR
Joined: 09 Nov 2011 Posts: 14
|
|
Posted: Sat Nov 12, 2011 1:58 pm |
|
|
Ttelmah wrote: | Key reason this won't do what you want, is using the delay in the interrupt.
The compiler will be giving you a warning here.
Problem is that the chip does not support 're-entrant code'. This is where you call a routine from inside itself (basically very difficult to implement, unless the chip has a variable stack, which the PIC does not.....).
Now, because you also have a delay called in the external 'main' code, interrupts _will_ be disabled for the entire 500mSec while this executes, to prevent the second delay from being called....
|
SO you mean to say that Timer 0 ISR is itself a routine, and calling a delay routine in it will cause a bad effect on the job.
Is that it? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Sat Nov 12, 2011 3:41 pm |
|
|
Not quite.
You are calling a delay routine in the interrupt, and also a delay routine in the main. The compiler _must_ prevent the first happening inside the second, so will disable interrupts for the entire delay routine in the main.
A compiler warning, saying that this is being done will be given (unless you have this warning turned off).
General rule of thumb with interrupts, is inside the handler _do the least possible_. In my example, I just decrement the two clock counters, nothing else. Then all led changes etc., are done in the external code.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|