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

Doubt in interrupt processing
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
jacktaylor



Joined: 02 Sep 2017
Posts: 75

View user's profile Send private message Send e-mail

Doubt in interrupt processing
PostPosted: Sun Jul 08, 2018 8:46 am     Reply with quote

Hello friends. I have a doubt in the execution of an interruption in the TIMER1 of the example, but that also applies to the TIMER0.
In the next program, the timer overflow is 131ms.
The doubt is: when overflow occurs the lines within the while (1) stop executing and the processing is done inside the interrupt lines ? Is the following executed or not ?
Code:

FOR (REPEAT = 0; REPEAT <2; REPEAT ++);
  {
   OUTPUT_A (0XFF);
   DELAY_MS (500);
   OUTPUT_A (0X00);
   DELAY_MS (500);
  }

Since to execute for () demand a delay time of 2 seconds and at this time the timer should already be at least 16 times.

In my simulation, the is executed only once and does not obey the REPEAT <2 times.
Code:

#FUSES INTRC_IO, NOWDT, NOMCLR     
#USE DELAY(clock= 4M)

#use fast_io(a)
#use fast_io(b)

INT REPETE;
INT16 RECEBE;

#int_timer1
void timer_1()
{   
SET_TIMER1(0);   
           
FOR (REPETE =0; REPETE<2; REPETE++);
  {
   OUTPUT_A(0XFF);
   DELAY_MS(500);
   OUTPUT_A(0X00);
   DELAY_MS(500);
  }
 
}


void main()
{

SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_2  );
SET_TIMER1(0);
ENABLE_INTERRUPTS(INT_TIMER1);
ENABLE_INTERRUPTS(GLOBAL);

SET_TRIS_A(0X00);
OUTPUT_A(0X00);
SET_TRIS_B(0X00);
OUTPUT_B(0X00);
 
WHILE(1)
{       

       RECEBE= GET_TIMER1();
       OUTPUT_B(RECEBE);
}
Rolling Eyes
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jul 08, 2018 9:14 am     Reply with quote

2 quick comments.

1st. FOR (REPEAT = 0; REPEAT <2; REPEAT ++);
can only be executed once as repeat starts at 0, increments to 1 and when it goes to 2, exits the loop

2nd. you should never,ever have 'delays' of any kind within any ISRs. same holds true for prints ,floating point math and 'complicated' decisions.

also no processor is shown....

and .. 'simulation', if Proteus, please read PIC101 sticky and get rid of Proteus.
jacktaylor



Joined: 02 Sep 2017
Posts: 75

View user's profile Send private message Send e-mail

PostPosted: Sun Jul 08, 2018 11:10 am     Reply with quote

temtronic wrote:
2 quick comments.

1st. FOR (REPEAT = 0; REPEAT <2; REPEAT ++);
can only be executed once as repeat starts at 0, increments to 1 and when it goes to 2, exits the loop

2nd. you should never,ever have 'delays' of any kind within any ISRs. same holds true for prints ,floating point math and 'complicated' decisions.

also no processor is shown....

and .. 'simulation', if Proteus, please read PIC101 sticky and get rid of Proteus.



Okay, thanks for the information Ttelmah. I made the code to better understand how the interruption works. The intention is not to use delay in the interrupt, but to understand the actual processing. I did this to understand a video lesson I watched, but it did not work as shown in the lesson simulation.
However, even if REPEAT with a larger loop, for example 5 times FOR (REPEAT = 0; REPEAT <6; REPEAT ++) ;, the PORT only varies once, ie regardless of the REPEAT value, only the loop will be executed once FOR, when the interruption occurs, because this is what is happening in my assembly on the protoboard, very different from what I saw in a video lesson, where the author puts REPEAT <10 and the PORT rises 9 times and not only once as it is happening with my simulation. In my simulation it continues to run only once.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Sun Jul 08, 2018 12:51 pm     Reply with quote

Jay (Temtronic), is not me. Smile

It should sit practically never executing the output B instruction. Basically the interrupt handler you have takes longer than the time between interrupts, so whenever it exits it'll immediately trigger again. There are total of about 10 instructions in your main loop, and just one will get executed each time the code returns to the main.
If you want to see ten pulses when the timer triggers run the code without the delays.
You talk about a 'simulation' if this is the Proteus simulator, this is full of bugs. If you want to run a simulator get the old MPLAB 8.92, which has one that 99% works. In all cases though the simulation will only give reasonable results if you have set it up correctly.
There is no point in setting the timer to zero in the interrupt. The interrupt triggers when the timer resets to zero.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jul 08, 2018 4:50 pm     Reply with quote

temtronic wrote:

FOR (REPEAT = 0; REPEAT <2; REPEAT ++);
can only be executed once as repeat starts at 0, increments to 1 and
when it goes to 2, exits the loop.

Actually the loop count is OK. It should execute the loop 2 times.
What's wrong is that he has a semi-colon ';' at the end of the for()
statement.
Quote:
FOR (REPEAT = 0; REPEAT <2; REPEAT ++); <== semi-colon here is wrong

When you have a semi-colon at the end of a for() statement,
it will just count down and exit the for() line. Then it will
execute the body of the loop one time. That's what he is seeing.
jacktaylor



Joined: 02 Sep 2017
Posts: 75

View user's profile Send private message Send e-mail

PostPosted: Mon Jul 09, 2018 7:03 am     Reply with quote

PCM programmer wrote:
temtronic wrote:

FOR (REPEAT = 0; REPEAT <2; REPEAT ++);
can only be executed once as repeat starts at 0, increments to 1 and
when it goes to 2, exits the loop.

Actually the loop count is OK. It should execute the loop 2 times.
What's wrong is that he has a semi-colon ';' at the end of the for()
statement.
Quote:
FOR (REPEAT = 0; REPEAT <2; REPEAT ++); <== semi-colon here is wrong

When you have a semi-colon at the end of a for() statement,
it will just count down and exit the for() line. Then it will
execute the body of the loop one time. That's what he is seeing.



Ohhhhh my God. I made a grotesque mistake by leaving the semicolon. This is exactly the error of not executing FOR. Many thanks PCM programmer, but it was nice to be aware and it was more an apprenticeship. Thanks a lot for the help. Embarassed Wink
jacktaylor



Joined: 02 Sep 2017
Posts: 75

View user's profile Send private message Send e-mail

PostPosted: Mon Jul 09, 2018 7:17 am     Reply with quote

jacktaylor wrote:
PCM programmer wrote:
temtronic wrote:

FOR (REPEAT = 0; REPEAT <2; REPEAT ++);
can only be executed once as repeat starts at 0, increments to 1 and
when it goes to 2, exits the loop.

Actually the loop count is OK. It should execute the loop 2 times.
What's wrong is that he has a semi-colon ';' at the end of the for()
statement.
Quote:
FOR (REPEAT = 0; REPEAT <2; REPEAT ++); <== semi-colon here is wrong

When you have a semi-colon at the end of a for() statement,
it will just count down and exit the for() line. Then it will
execute the body of the loop one time. That's what he is seeing.



Ohhhhh my God. I made a grotesque mistake by leaving the semicolon. This is exactly the error of not executing FOR. Many thanks PCM programmer, but it was nice to be aware and it was more an apprenticeship. Thanks a lot for the help. Embarassed Wink


With this test I was able to verify that:
1) When executing the interrupt while (1) processing is interrupted, even the overflow time being 131ms, ie no new interrupts occur while not executing the entire loop within the interrupt.
2) there is no need to use clear_interrupt (INT_TIMER1); in CCS compiler? I did the test with and without this function and the result was the same.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Mon Jul 09, 2018 7:35 am     Reply with quote

Quote:

When executing the interrupt while (1) processing is interrupted, even the overflow time being 131ms, ie no new interrupts occur while not executing the entire loop within the interrupt.


Actually they do occur. However the default behaviour is to automatically clear interrupts _at the end of the handler_. So they will be clear when you exit.

There is an option 'NOCLEAR' that can be appended to the interrupt handler declaration, which disables this option, and you then have to clear the interrupts yourself. I must admit I normally do this since I prefer interrupts to be cleared at the start of the handler, which then allows subsequent 'second triggers' to also be seen.
jacktaylor



Joined: 02 Sep 2017
Posts: 75

View user's profile Send private message Send e-mail

PostPosted: Mon Jul 09, 2018 8:17 am     Reply with quote

Ttelmah wrote:
Quote:

When executing the interrupt while (1) processing is interrupted, even the overflow time being 131ms, ie no new interrupts occur while not executing the entire loop within the interrupt.


Actually they do occur. However the default behaviour is to automatically clear interrupts _at the end of the handler_. So they will be clear when you exit.

There is an option 'NOCLEAR' that can be appended to the interrupt handler declaration, which disables this option, and you then have to clear the interrupts yourself. I must admit I normally do this since I prefer interrupts to be cleared at the start of the handler, which then allows subsequent 'second triggers' to also be seen.



In your case you use the not clear 'NOCLEAR' in the declaration of void main () and then you use clear_interrupt (INT_TIMERXX); ?
Let me see if I got it. Can I use the clean interruption? Or do I need to declare 'NOCLEAR'?

Code:
# int_timer1
void timer_1 ()
{
      CLEAR_INTERRUPT(INT_TIMER1);
       SET_TIMER1 (0);
          TEMPO ++;
       IF (TIME == 5)
       {
         for (REPEAT = 0; REPEAT <6; REPEAT ++)
          {
                OUTPUT_A (0XFF); // OUTPUT_HIGH (PIN_D7);
                 OUTPUT_A (0X00); // OUTPUT_LOW (PIN_D7);
             
          }
       }
 
}

void main ()
{

CLEAR_INTERRUPT (INT_TIMER1);
SETUP_TIMER_1 (T1_INTERNAL | T1_DIV_BY_2);
SET_TIMER1 (0);
ENABLE_INTERRUPTS (INT_TIMER1);
ENABLE_INTERRUPTS (GLOBAL);

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Mon Jul 09, 2018 8:28 am     Reply with quote

It's entirely up to you.

However if your interrupt was something like an event you wanted to count, the quite large time it takes to get _out_ of the interrupt becomes significant. So in this case you'd want to move the clear towards the front of the interrupt (so use the NOCLEAR, and clear it yourself). The interrupt could then re-trigger and the handler be called again. However for an event where you don't mind missing a occasional trigger, or the interval between triggers is always more than the time needed to get into the handler and out again, the default behaviour is fine:
Code:

# int_timer1
void timer_1 ()
{
      CLEAR_INTERRUPT(INT_TIMER1);
      //A wasted instruction. The interrupt is being cleared again
      //at the end of the handler
       SET_TIMER1 (0);
      //This is also a wasted instruction. The interrupt is called
      //because the timer _has_ wrapped to zero...
          TEMPO ++;
       IF (TIME == 5)
       {
         for (REPEAT = 0; REPEAT <6; REPEAT ++)
          {
                OUTPUT_A (0XFF); // OUTPUT_HIGH (PIN_D7);
                 OUTPUT_A (0X00); // OUTPUT_LOW (PIN_D7);
             
          }
       }
jacktaylor



Joined: 02 Sep 2017
Posts: 75

View user's profile Send private message Send e-mail

PostPosted: Tue Jul 10, 2018 7:59 am     Reply with quote

Ttelmah wrote:
It's entirely up to you.

However if your interrupt was something like an event you wanted to count, the quite large time it takes to get _out_ of the interrupt becomes significant. So in this case you'd want to move the clear towards the front of the interrupt (so use the NOCLEAR, and clear it yourself). The interrupt could then re-trigger and the handler be called again. However for an event where you don't mind missing a occasional trigger, or the interval between triggers is always more than the time needed to get into the handler and out again, the default behaviour is fine:
Code:

# int_timer1
void timer_1 ()
{
      CLEAR_INTERRUPT(INT_TIMER1);
      //A wasted instruction. The interrupt is being cleared again
      //at the end of the handler
       SET_TIMER1 (0);
      //This is also a wasted instruction. The interrupt is called
      //because the timer _has_ wrapped to zero...
          TEMPO ++;
       IF (TIME == 5)
       {
         for (REPEAT = 0; REPEAT <6; REPEAT ++)
          {
                OUTPUT_A (0XFF); // OUTPUT_HIGH (PIN_D7);
                 OUTPUT_A (0X00); // OUTPUT_LOW (PIN_D7);
             
          }
       }



Okay, thanks for the explanation, Ttelmah, I get it. Now I have another question with the CCS compiler.
In the test program below, I verify that by assigning zero the variable TMR1IF of PIR1 it does not return to one, simulating in MPLAB 8.92, with step by step F7. If I remove the line that assigns zero, in the Proteus simulation the program runs executing normally the For in the while (1). The point is that the manual has to reset this interrupt flag. The doubts are: Because when zeroing, the bit does not return to one and in the Proteus simulation does the program normally run without zeroing this flag in the CCS?

Code:

#include <16F628A.h>
#FUSES INTRC_IO, NOWDT, NOMCLR // 16F628A     
#use delay(clock= 4M)
#use fast_io(b)
#bit TMR1IF = 0x0C.0

INT REPETE;
INT16 RECEBE;
void main()
{
//clear_interrupt(INT_TIMER1);
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_2  );
//SETUP_TIMER_1(T1_EXTERNAL);
SET_TIMER1(65533);
//ENABLE_INTERRUPTS(INT_TIMER1);
//ENABLE_INTERRUPTS(GLOBAL);


SET_TRIS_A(0X00);
OUTPUT_A(0X00);
SET_TRIS_B(0X80);
OUTPUT_B(0X00);

     WHILE(1)
   {         
           RECEBE= GET_TIMER1();
            OUTPUT_B(RECEBE);
           
      IF (TMR1IF)

       {TMR1IF =0;
           FOR (REPETE =0; REPETE<3; REPETE++)
            {
               OUTPUT_A(0XFF);//OUTPUT_HIGH(PIN_D7);
               DELAY_MS(1);
               OUTPUT_A(0X00);//OUTPUT_LOW(PIN_D7);
               DELAY_MS(1);
             }
        }
     }     
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Tue Jul 10, 2018 8:19 am     Reply with quote

Repeat 15*.

Do not believe the Proteus simulator.

On a real chip it triggers again and merrily executes the output every 131mSec.
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jul 10, 2018 12:03 pm     Reply with quote

As Mr. T. say
Do NOT believe Proteus ! It's BUSTED, broke, incomplete, worthless...
Sadly there's a whole herd of folks who think Proteus is the next best thing to sliced bread...
however it's NOT a 100% perfect 'simulator' for PICs.
Even the schematic creator is flawed. In 10+ years here, I've yet to see ONE schematic that would work in the real World...not ONE !!

If you want to see what your code's really doing, dump the listing, grab the instruction set, pad of graph paper and pencil then 'play computer'. YOU manual 'single step' through every line of code..diddle registers and such, just like the PIC. Old school..best way to learn.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Tue Jul 10, 2018 12:16 pm     Reply with quote

As a comment I have just tried it in MPLAB 8.92, which the poster mentions, and in this the flag does set again merrily. If you put a break on the TMRIF=0 instruction, it happily arrives back there with the bit set. Remember this is the _only_ place you can test this, since this then immediately sets it back to 0....
jacktaylor



Joined: 02 Sep 2017
Posts: 75

View user's profile Send private message Send e-mail

PostPosted: Tue Jul 10, 2018 3:52 pm     Reply with quote

Ttelmah wrote:
As a comment I have just tried it in MPLAB 8.92, which the poster mentions, and in this the flag does set again merrily. If you put a break on the TMRIF=0 instruction, it happily arrives back there with the bit set. Remember this is the _only_ place you can test this, since this then immediately sets it back to 0....



Ok thanks friend Ttelmah, I did another simulation in MPLAB and this time I saw the TMR1IF flag go to zero. Laughing
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