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

Timer0 interrupt

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



Joined: 24 Oct 2011
Posts: 50

View user's profile Send private message

Timer0 interrupt
PostPosted: Fri Nov 11, 2011 7:21 am     Reply with quote

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);
  ;
  }
}
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Fri Nov 11, 2011 9:06 am     Reply with quote

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.
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Fri Nov 11, 2011 9:17 am     Reply with quote

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
SSR



Joined: 09 Nov 2011
Posts: 14

View user's profile Send private message AIM Address

PostPosted: Sat Nov 12, 2011 1:58 pm     Reply with quote

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?
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sat Nov 12, 2011 3:41 pm     Reply with quote

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
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