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

Timer 0 interrupt doesn't work correct.
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

Timer 0 interrupt doesn't work correct.
PostPosted: Mon Nov 26, 2012 1:41 pm     Reply with quote

In this code I'm trying to make phase shifting of incoming signal. Here is the code:
Code:

#include <16f684.h>
#fuses NOMCLR,INTRC
#use delay(clock  = 8M)
#use rs232 (baud=9600, xmit=PIN_C0,rcv=PIN_C2)
#define outp pin_c3
#PRIORITY INT_TIMER0,INT_RA,INT_TIMER1

unsigned int16 tval,per;
int1 sync_done=0;

void sync();

#INT_TIMER0
tmr0()
{
output_low(outp);
disable_interrupts(INT_TIMER0);
}

#INT_TIMER1
tmr1()
{
output_high(outp);
set_timer0(0);
enable_interrupts(INT_TIMER0);
}

#INT_RA
void I_RA1()
   {
   output_low(outp); 
   
   if(sync_done)
      {
      if(input(pin_a1)); //read port A     
      tval-=20;
      set_timer1(65535-tval); //makes TMR1 to overflow after tval seconds
      }
   else
      {
      if(input(pin_a1));   //read port A
      tval=get_timer1();
      set_timer1(0);
      }
    }
void main ()
{

SETUP_TIMER_0(T0_INTERNAL|T0_DIV_8);  //overflows every 1ms
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_2); //overflows  every 65.5ms
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
SET_TIMER1(0);
sync();
while(true)
   {
   
   }
}

void sync()
{
printf("Syncronizinc in process...");
delay_ms(1000);
sync_done=1;
tval=tval-50;
per=tval;
printf("  %lu",tval);
}

My question is, Why timer 0 doesn't wait 1ms (256x4us) before activate interruption? It goes into an interruption immediately after INT_TIMER1 function being expired.
dyeatman



Joined: 06 Sep 2003
Posts: 1924
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Nov 26, 2012 1:57 pm     Reply with quote

Disabling the interrupt does not stop the timer. It continues to run and over flow.
_________________
Google and Forum Search are some of your best tools!!!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Mon Nov 26, 2012 3:29 pm     Reply with quote

Also, setting the timer to a value, does not clear the interrupt flag. So to make the timer trigger in a known count, you need:
Code:

set_timer0(val);
clear_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER0);


Best Wishes
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Nov 26, 2012 9:26 pm     Reply with quote

And don't enable the interrupt inside the interrupt.

That's a useless instruction -- if the interrupt wasn't enabled, the code inside the interrupt wouldn't be executing.

The CCS interrupt handler takes care of clearing interrupts for you in general. You typically do not need clear/enable inside the ISR.


-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 12:29 am     Reply with quote

He is enabling Timer0, inside Timer1. This is a perfectly reasonable way of giving one delay after another.

Best Wishes
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 2:59 am     Reply with quote

Ttelmah wrote:
He is enabling Timer0, inside Timer1. This is a perfectly reasonable way of giving one delay after another.


Sorry - my bad.

That's legit indeed.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 3:27 am     Reply with quote

Ttelmah, where exactly in my code I need to clear_interrupts(int_timer0)?
Mike Walne



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

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 3:27 am     Reply with quote

Quote:
My question is, Why timer 0 doesn't wait 1ms (256x4us) before activate interruption? It goes into an interruption immediately after INT_TIMER1 function being expired.

You're doing this at the start of main.
Code:
SETUP_TIMER_0(T0_INTERNAL|T0_DIV_8);  //overflows every 1ms
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_2); //overflows  every 65.5ms

By the time you get into the timer1 ISR timer0 will have overflowed several times, setting the interrupt flag in the process.

When you do this in the timer1 ISR
Code:

set_timer0(0);
enable_interrupts(INT_TIMER0);

You don't have to wait for timer0 to overflow, the interrupt flag has already been set. Enabling the interrupt has the effect of enabling the interrupt routine only, it does not control the timers ability to set the interrupt flag. This is why you need to follow Ttelmah's instructions. It might also be an idea to either stop timer0 or disable timer0 interrupts in the timer0 ISR, to prevent it from repeatedly firing.

Mike

Your Int_RA code is superfluous to this thread.
Mike Walne



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

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 3:31 am     Reply with quote

Quote:
Ttelmah, where exactly in my code I need to clear_interrupts(int_timer0)?

You should not need to clear interrupts. It's supposed to be automatic, except maybe on initialisation.

Mike
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 3:37 am     Reply with quote

Ttelmah, where exactly in my code I need to clear_interrupts(int_timer0)?
Why I need to do this? Hasn't it done automatically by interrupt handler, as batman says?
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 5:03 am     Reply with quote

The interrupt is cleared at the end of the interrupt handler automatically, for the interrupt that called that handler. _But not for any other interrupt_.

You are attempting to start the timer0 interrupt, from inside the timer1 routine. When you arrive at timer1, the timer0 interrupt flag will already be set, since it occurs more frequently than timer1, and you have the interrupt disabled (so the handler won't have been called, and the interrupt won't have been automatically cleared).

So, when you use:
Code:

#INT_TIMER1
void tmr1(void) {
   output_high(outp);
   set_timer0(0);
   enable_interrupts(INT_TIMER0);
}
//At this point, as soon as you exit the routine. the timer0 interrupt will _immediately_ be called, since the flag is already set.....


To have timer0 trigger the defined time _after_ this point, you need to clear the flag. So:
Code:

#INT_TIMER1
void tmr1(void) {
   output_high(outp);
   set_timer0(0);
   clear_interrupts(INT_TIMER0);
   enable_interrupts(INT_TIMER0);
}


You need to get your head round the fact the once the timer is started, it runs continuously. Whenever it wraps from 0xFFFF to 0, the interrupt flag is set. This happens whether the interrupt is enabled or not. Then if the interrupt is enabled, and the global interrupt is enabled, the handler will be called. If the flag is already set when you enable the interrupt, the handler will be called ASAP, without waiting for the next 'wrap.
Since the timer is running with the interrupt disabled, the automatic clearing in the handler won't happen, so you have to clear the interrupt yourself.

Yes, you should only need to clear interrupts manual during 'initialisation', but this is the initialisation of the timer0 interrupt......

Best Wishes
Mike Walne



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

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 8:46 am     Reply with quote

An alternative is to enable timer0 in the timer1 ISR and disable it in the timer0 ISR.
No need for enabling/disabling interrupt, clearing interrupt, or setting timer0.
It's fewer instructions and will produce slightly different timings which may (or may not) be more accurate.
I suspect the two delays in getting into each of the two ISRs will largely cancel each other.

Mike

EDIT I'm not saying one way is better than the other, just a different approach.
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 10:05 am     Reply with quote

Yes.
You'd need to set timer0, to zero in the main before starting (the timer registers are _undefined_ on start-up) but once this is done, then just start and stop the actual timer as required.
Has the advantage of fractionally reducing power consumption.

Best Wishes
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 12:50 pm     Reply with quote

Guys YOU ARE GREAT! I changed my code to this:
Code:

#INT_TIMER0
void tmr0()
{
output_low(outp);
}

#INT_TIMER1
void tmr1()
{
output_high(outp);
enable_interrupts(INT_TIMER0);
clear_interrupt(INT_TIMER0);
set_timer0(0);
}

and what I want happened.
The information I got from your posts is very valuable for me.
Now Slow Start for my AC induction monophase motor is done.
Thank you again!
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Tue Nov 27, 2012 1:30 pm     Reply with quote

There is one tiny problem that may happen occasionally.
Because you set the timer after clearing the interrupt, once in 65536 times, the timer can wrap on the instruction between the interrupt being cleared, and the timer being reset. This will cause the original problem to come back...
The order of the instructions given in the original post avoids this....

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 1, 2  Next
Page 1 of 2

 
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