View previous topic :: View next topic |
Author |
Message |
cleberalbert
Joined: 25 Feb 2014 Posts: 34 Location: Brazil
|
Rotate pieces of code for each timer0 overflow |
Posted: Tue Aug 02, 2016 7:46 am |
|
|
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
|
|
Posted: Tue Aug 02, 2016 8:08 am |
|
|
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 : :
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: 19545
|
|
Posted: Tue Aug 02, 2016 10:37 am |
|
|
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: 9244 Location: Greensville,Ontario
|
|
Posted: Tue Aug 02, 2016 10:40 am |
|
|
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: 297
|
|
Posted: Tue Aug 02, 2016 12:21 pm |
|
|
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
|
|
Posted: Tue Aug 02, 2016 4:29 pm |
|
|
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: 19545
|
|
Posted: Wed Aug 03, 2016 12:25 am |
|
|
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. |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Wed Aug 03, 2016 2:53 pm |
|
|
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
Best wishes
Joe |
|
|
|