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

Rotate pieces of code for each timer0 overflow

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



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

Rotate pieces of code for each timer0 overflow
PostPosted: Tue Aug 02, 2016 7:46 am     Reply with quote

Hello all!!

I'm using timer0 interruption to perform 4 actions (4 code blocks in the same interrupt service routine), but I want to execute only 1 action (1 block) for each timer0 overflow in order.

ex:
1st overflow: execute 1st block
2nd overflow: execute 2nd block
3rd overflow: execute 3rd block
4th overflow: execute 4th block
1st overflow: execute 1st block
2nd overflow: execute 2nd block
And so on...repearts forever.


Actualy my code executes all blocks (whole function) every timer0 overflow. How can I do to "rotate" the blocks?

Tks in advance!

My code:
Code:

#include <16F676.h>

#device ADC=10

#FUSES NOWDT
#FUSES INTRC_IO
#FUSES NOPUT
#FUSES NOPROTECT
#FUSES NOBROWNOUT
#FUSES NOMCLR
#FUSES NOCPD
#FUSES RESERVED                 //Used to set the reserved FUSE bits
 
#use delay(clock=4000000)

#define OUT1   PIN_A5
#define OUT2   PIN_C1
#define OUT3   PIN_C2
#define OUT4   PIN_C3
#define OUT5   PIN_C4

#INT_RTCC
void  RTCC_isr(void)
{
   disable_interrupts(INT_RTCC);

   //BLOCK 1
   output_bit(OUT1, TRUE);
   delay_us(500);
   output_bit(OUT1, FALSE);

   //BLOCK 2
   output_bit(OUT2, TRUE);
   delay_us(750);
   output_bit(OUT2, FALSE);

   //BLOCK 3
   output_bit(OUT3, TRUE);
   delay_us(1000);
   output_bit(OUT3, FALSE);

   //BLOCK 4
   output_bit(OUT4, TRUE);
   delay_us(1250);
   output_bit(OUT4, FALSE);

   enable_interrupts(INT_RTCC);
}

void main()
{   
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_bit);      //4,0 ms overflow

   while(TRUE);
}
cleberalbert



Joined: 25 Feb 2014
Posts: 34
Location: Brazil

View user's profile Send private message

PostPosted: Tue Aug 02, 2016 8:08 am     Reply with quote

I got it! I'm rotating the blocks through a global variable to count how many overflow has already happened. I had tried it before and didn't work but it may be some mistake. Now is working :Smile :

This code is a prototype I wrote to simplify your understanding. Now I'll try to implement in my original code.

To rotate the blocks:
Code:

#include <16F676.h>

#device ADC=10

#FUSES NOWDT
#FUSES INTRC_IO
#FUSES NOPUT
#FUSES NOPROTECT
#FUSES NOBROWNOUT
#FUSES NOMCLR
#FUSES NOCPD
#FUSES RESERVED                 //Used to set the reserved FUSE bits
 
#use delay(clock=4000000)

#define OUT1   PIN_A5
#define OUT2   PIN_C1
#define OUT3   PIN_C2
#define OUT4   PIN_C3
#define OUT5   PIN_C4

int count = 0;

#INT_RTCC
void  RTCC_isr(void)
{
   disable_interrupts(INT_RTCC);
   
   count++;

   switch(count)
      {
      case 1:
         {   
            //BLOCK 1
            output_bit(OUT1, TRUE);
            delay_us(250);
            output_bit(OUT1, FALSE);
         }
         break;
      case 2:
         {   
            //BLOCK 2
            output_bit(OUT2, TRUE);
            delay_us(500);
            output_bit(OUT2, FALSE);
         }
         break;
      case 3:
         {   
            //BLOCK 3
            output_bit(OUT3, TRUE);
            delay_us(1250);
            output_bit(OUT3, FALSE);
         }
         break;
      case 4:
         {   
            //BLOCK 4
            output_bit(OUT4, TRUE);
            delay_us(1500);
            output_bit(OUT4, FALSE);
            count = 0;
         }
         break;
      }
   enable_interrupts(INT_RTCC);
}

void main()
{   
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_bit);      //4,0 ms overflow

   while(TRUE);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Tue Aug 02, 2016 10:37 am     Reply with quote

Honestly though, why get involved in the overhead of an interrupt?.

Just poll the RTCC:
Code:


void main()
{   
   int8 count=0;
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_bit);      //4,0 ms overflow

   while(TRUE
   {
       if (interrupt_active(INT_RTCC)
       {
           clear_interrupt(INT_RTCC);
           switch(++count)
           {
           case 1:
               //BLOCK 1
               output_high(OUT1);
               delay_us(250);
               output_low(OUT1);
               break;
           case 2:
               //BLOCK 2
               output_high(OUT2;
               delay_us(500);
               output_low(OUT2);
               break;
           case 3:
               //BLOCK 3
               output_high(OUT3);
               delay_us(1250);
               output_low(OUT3);
               break;
           case 4:
               //BLOCK 4
               output_high(OUT4);
               delay_us(1500);
               output_low(OUT4);
               count = 0;
               break;
           }
        }       
    }
}


Last edited by Ttelmah on Tue Aug 02, 2016 10:51 am; edited 1 time in total
temtronic



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

View user's profile Send private message

PostPosted: Tue Aug 02, 2016 10:40 am     Reply with quote

you're 1/2way there.

you 'should' move your 'switch' code to main()
The ISR will 'say' the interrupt has happend and increment the counter variable. Your 'case' code will decide what to do.

Just be SURE to reset the counter variable after getting to 4 !

Jay
guy



Joined: 21 Oct 2005
Posts: 291

View user's profile Send private message Visit poster's website

PostPosted: Tue Aug 02, 2016 12:21 pm     Reply with quote

cleberalbert, please note that you should not disable/enable the interrupt in the interrupt service routine. All interrupts* are disabled and re-enabled automatically during interrupt handling.

* In more advanced PICs there are interrupt priorities where one interrupt can interrupt another.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

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

PostPosted: Tue Aug 02, 2016 4:29 pm     Reply with quote

As Guy has said, the compiler enables/disables interrupts so your enable disable is not necessary.
Ttelmah program big advantage is that you don't need to wait your delays inside the isr.

Best wishes
Joe
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Wed Aug 03, 2016 12:25 am     Reply with quote

gjs_rsdi wrote:
As Guy has said, the compiler enables/disables interrupts so your enable disable is not necessary.
Ttelmah program big advantage is that you don't need to wait your delays inside the isr.

Best wishes
Joe


Slightly more than that. There is quite a bit of code involved in the interrupt handler (and time), to get to the interrupt routine. With the 'polled' code, the functions will be happening within just a couple of instruction times of the interrupt triggering, and the code will be smaller.
The delays in the ISR, in this case don't matter, since he is not using delays anywhere else!...

Polling the interrupt, will give smaller, and faster code. Very Happy
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

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

PostPosted: Wed Aug 03, 2016 2:53 pm     Reply with quote

Two questions Ttelmah:
1. The interrupt itself is disabled if I understand correct?
2. If I have to do other things in the program that takes let's say 100us before back to main, my pooling can have this delay. Any way to avoid the delay?
From Ttelmah:
Quote:
There is quite a bit of code involved in the interrupt handler (and time), to get to the interrupt routine.

I will say quite a lot of time to enter/exit the isr. Some way to shorten it?
I forget how I was doing it in assembler Sad

Best wishes
Joe
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