|
|
View previous topic :: View next topic |
Author |
Message |
x!NdY Guest
|
of Interrupts and functions.. |
Posted: Thu Jul 17, 2008 9:30 pm |
|
|
hi everybody.. my problem is that how can i go to a particular function once an interrupt is triggered..
e.g.
Code: |
void func1()
{
//some process here
.
.
.
trigFunc=false;
}
void main()
{
enable_interrupts(INT_TIMER1);
enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);
do{
.
.
.
.
}while(1);
}
#int_TIMER1
void TIMER1_isr()
{
bit_clear(T1CON,7);
Bit_Set(TMR1H,7);
Bit_Set(T1CON,7);
if (++sec>59){
sec=0;
trigFunc=true; // to trigger func1
if(++min>59){
min=0;
if(++hour>23){
hour=0;
++days;
if ((days == 29 && Month== 2 && !IS_LEAP(Year))
|| (days == 30 && Month==2)
|| (days == 31 && (month==4 || month==6 || month==9 || month==11))
|| (days == 32)
){month++;days=0;}
if(month == 13) {year++; month=0;}
}
}
}
}
|
how can i do this so that when trigFunc = true then it will go directly to func1.. I dont want to place
Code: |
if (trigFunc)
func1();
|
in the main code since it will create some delay if the MCU is still processing some data in some part of the program. how can i do this so that when trigFunc is true, it will leave what it is doing and go directly to func1. After func1 is Finished then it will continue what it was doing..
thanks...
im using V4.068.. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 18, 2008 11:23 am |
|
|
Quote: | when trigFunc is true, it will leave what it is doing and go directly to
func1. After func1 is Finished then it will continue what it was doing. |
That's what an interrupt does. Call func1 from the interrupt routine. |
|
|
x!NdY Guest
|
|
Posted: Mon Jul 21, 2008 8:21 pm |
|
|
hi.. if i call the function in the interrupt like this:
Code: |
#int_TIMER1
void TIMER1_isr()
{
bit_clear(T1CON,7);
Bit_Set(TMR1H,7);
Bit_Set(T1CON,7);
if (++sec>59){
sec=0;
func1(); // -------- > func1 called
if(++min>59){
min=0;
if(++hour>23){
hour=0;
++days;
if ((days == 29 && Month== 2 && !IS_LEAP(Year))
|| (days == 30 && Month==2)
|| (days == 31 && (month==4 || month==6 || month==9 || month==11))
|| (days == 32)
){month++;days=0;}
if(month == 13) {year++; month=0;}
}
}
}
}
|
will it create a delay in the timer since the compiler sees func1 as part of the interrupt code and will try to finish it before it will continue its calculation of sec, min, hour etc. ? what i want is when the program is in func1, the interrupt will be left out and will continue its normal operation every time it is triggered. or i am missing something here?
please help.. thanks.. |
|
|
Ttelmah Guest
|
|
Posted: Tue Jul 22, 2008 2:40 am |
|
|
You can't really have both.
You have a single processor, that is only capable of doing one thing at a time.
On 16 chips, if your interrupt even, needs to be handled all the time, then you need to use the original approach you outlined, having func1 in the main code, and setting a flag, to call it when required. This will introduce delays.
The alternative is to put it into the interrupt handler, in which case, while it is being handled,the rest of the interrupt code will not be executing.
There is a third possibility, on '18' chips, but it involves some fairly tricky programming, and good knowledge of how the chip works.
What you can do, is to shift timer1, to be a 'high priority' interrupt. Then chose another interrupt, _which never normally becomes triggered. Ideally use something like INT_EXT2, while having the pin for this set as an output, so the interrupt can never trigger. Set this as a low priority interrupt, and have it enabled. Put 'func1' into the handler for this interrupt. Now, since the interrupt never gets triggered, func1, will never be called. What you then do, is in your timer1 interrupt, when you want func1 to be triggered, you _set_ the interrupt bit. Then when the code returns from the high priority interrupt, the EXT2 low priority code will be called, executing func1. Since this is a low priority interrupt, timer1, can still execute.
Best Wishes |
|
|
x!NdY Guest
|
|
Posted: Tue Jul 22, 2008 10:17 pm |
|
|
hi Ttelmah.. thanks for your reply. i really appreciate it.. however, i tried your suggestion with this sample program i created. but, it doesnt give the result that i expect it to show..
here is my code:
Code: |
#include <18F4525.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOIESO //NO Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOPBADEN //NO PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES MCLR //Master Clear pin enabled
#FUSES NOLPT1OSC //Timer1 configured for higher power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_D4, rcv=PIN_D5, stream=PC)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, stream=GSM)
#use i2c(master, sda=PIN_C4, scl=PIN_C3)
#Byte TMR1H = 0xFCF // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0xFCD //TIMER1 CONFIG REGISTER LOOK DATASHEET
#define IS_LEAP(year) (year%4 == 0)
#priority TIMER1,EXT2
int sec=0;
int min=0;
int hour=0;
int days=0;
int month=0;
int16 year=0;
int16 FinData=0;
int1 rda_flag=false;
#include <stdlib.h>
#include <string.h>
void func1()
{
fprintf(PC,"infunc");
fprintf(PC,"sec1 = %i",sec);
delay_ms(500);
delay_ms(500);
delay_ms(500);
delay_ms(500);
delay_ms(500);
delay_ms(500);
delay_ms(500);
delay_ms(500);
fprintf(PC,"sec2 = %i",sec);
}
void main()
{
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_EXT2);
enable_interrupts(GLOBAL);
setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);
do{
}while(1);
}
#int_EXT2
void EXT2_isr()
{
func1();
output_low(PIN_B2);
}
#int_TIMER1
void TIMER1_isr()
{
bit_clear(T1CON,7);
Bit_Set(TMR1H,7);
Bit_Set(T1CON,7);
if (++sec>59){
sec=0;
output_high(PIN_B2);
if(++min>59){
min=0;
if(++hour>23){
hour=0;
++days;
if ((days == 29 && Month== 2 && !IS_LEAP(Year))
|| (days == 30 && Month==2)
|| (days == 31 && (month==4 || month==6 || month==9 || month==11))
|| (days == 32)
){month++;days=0;}
if(month == 13) {year++; month=0;}
}
}
}
}
|
looking at func1. i tried to show the sec value at two different times but the results are the same.. sec1 = 0, sec2 = 0... i expect sec2 to be a value other than 0 since i assume that even if it is processing func1, the timer1 interrupt can still be triggered. so the sec will still increment. or i am making the wrong assumptions here? please help.. thanks in advance.. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Jul 25, 2008 7:57 am |
|
|
Code: | #priority TIMER1,EXT2 | This is not the method for creating two different interrupt levels, it only assigns priority to multiple interrupts at the same hardware interrupt level.
To activate support for the second interrupt level you have to set: Code: | #device HIGH_INTS=TRUE |
And then in your code specify the interrupts as explained in the manual: Quote: | A summary of the different kinds of PIC18 interrupts:
#INT_xxxx
Normal (low priority) interrupt. Compiler saves/restores key registers.
This interrupt will not interrupt any interrupt in progress.
#INT_xxxx FAST
High priority interrupt. Compiler DOES NOT save/restore key registers.
This interrupt will interrupt any normal interrupt in progress.
Only one is allowed in a program.
#INT_xxxx HIGH
High priority interrupt. Compiler saves/restores key registers.
This interrupt will interrupt any normal interrupt in progress.
#INT_GLOBAL
Compiler generates no interrupt code. User function is located
at address 8 for user interrupt handling. |
For ease of programming I recommend first to use the HIGH keyword and only when processor speed is an issue optimize it to use the FAST keyword.
For code examples search this forum for the keyword 'HIGH_INTS'. |
|
|
Edstroyer Guest
|
|
Posted: Wed Aug 06, 2008 7:33 pm |
|
|
Actually you need to modify the stack.
below code should be at end of isr before leaving the isr
when the isr is returned, you will return to func1, not where the code was interrupted !
Code: |
fromisr=true; //fromisr is a global variable
pchi=*TOSH;// TOSH is a Special Function Register (SFR)
pclo=*TOSL; ////pclo is a global variable
stackptr=*STKPTR;//stackptr is a global variable defined depending on func1
----------------------------------
//typedef void (*fptr)(void);
//fptr faddr;
//to point to a function: void func1(void);
---------------------------------
//need to know value of STATUS and WREG before saving !
faddr = func1; //faddr is a pointer to function
faddrvalue = *faddr; //faddrvalue is a 16 bit unsigned int
*TOSH=make8(faddrvalue,1);
*TOSL=make8(faddrvalue,0);
|
this should help you a bit, but you need to understand what this is doing! or you can mess up your code , or get stack overflow/underflow errors
...then you need to do more work ! learn the PIC architecture you are using
the above code works for PIC18 architecture |
|
|
|
|
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
|