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

Help on 3 external interrupts at the same time PIC18F4550...

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



Joined: 24 Jan 2013
Posts: 53
Location: Brazil

View user's profile Send private message

Help on 3 external interrupts at the same time PIC18F4550...
PostPosted: Sat Aug 17, 2013 8:21 pm     Reply with quote

Hi All,

I need to read 3 external pulses at the same time and I'm planning to use external interrupts 0, 1 and 2 for that... however I'm trying to figure it out if that is going to work considering 2 or 3 pulses at the same time...

INT0 will be a car RPM, worse case 5000 RPM ~167Hz pulse frequency
INT1 will be a fuel flow measuring sensor, worse case 42LPH (Liters per Hour) ~45,5Hz pulse frequency
INT2 will be speed, worse case 140Km/h ~20Hz pulse frequency

How would be the best way to do it?

I'm using a PIC18F4550 (clock=48000000)

Any comments/suggestions would be appreciated!
Thanks
Hugo
_________________
Hugo Silva
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Sun Aug 18, 2013 4:19 am     Reply with quote

No problem at all, provided you follow the old 'adage', and keep the handlers quick.

Basically in a handler only either count, record a time, etc.. Don't do any arithmetic in the handlers. don't delay in the handlers etc.. Just record what needs to be recorded, nothing else.

The only time you'd get a problem, is if a combination of two handlers takes longer to process than the time between events on the third channel.

Best Wishes
younder



Joined: 24 Jan 2013
Posts: 53
Location: Brazil

View user's profile Send private message

code
PostPosted: Sun Aug 18, 2013 11:25 am     Reply with quote

Thanks for the reply,

I just did the code below and was wondering if it can be optimized...
Tmr1 is being used as a timebase in my application...
what does the PIC do when got 2 or 3 external pulse coming at the same time? it process INT0 then INT1 and so on according #priority INT_EXT, INT_EXT1, INT_EXT2, INT_TIMER0?
Any help would be appreciated!
Hugo

Code:

Float Time_Count_INT0=0.0,Time_Count_INT0_Mem[2]={0.0,0.0}; 
Float Time_Count_INT1=0.0,Time_Count_INT1_Mem[2]={0.0,0.0};
Float Time_Count_INT2=0.0,Time_Count_INT2_Mem[2]={0.0,0.0}; 
#INT_TIMER0             // Definition that next line will be associated to Timer0 interrupt
void timer0()           // Function called automaticaly 
  {
 
//Timer0 will not be reseted or restarted, it will continuously count till its overflow
         if (Time_Count_INT0_Mem[0]==0) {  //if no external interrupt has been called
         Time_Count_INT0=Time_Count_INT0+1.39810133333333; //Then add time counter by total tmr0 overflow -> 1.39810133333333= Total time for tmr0 overflow
         }
         else { //Time count must start from last tmr0 reset value
         Time_Count_INT0=Time_Count_INT0+((65536-Time_Count_INT0_Mem[0])*0.0000213333333333333); //1.39810133333333= Total time for tmr0 overflow
         Time_Count_INT0_Mem[0]=0; //clear time count mem 0
         Time_Count_INT0_Mem[1]=0; //clear time count mem 1
         }
         
         if (Time_Count_INT1_Mem[0]==0) {  //if no external interrupt has been called
         Time_Count_INT1=Time_Count_INT1+1.39810133333333; //Then add time counter by total tmr0 overflow -> 1.39810133333333= Total time for tmr0 overflow
         }
         else { //Time count must start from last tmr0 reset value
         Time_Count_INT1=Time_Count_INT1+((65536-Time_Count_INT1_Mem[0])*0.0000213333333333333); //1.39810133333333= Total time for tmr0 overflow
         Time_Count_INT1_Mem[0]=0; //clear time count mem 0
         Time_Count_INT1_Mem[1]=0; //clear time count mem 1
         }
         
         if (Time_Count_INT2_Mem[0]==0) {  //if no external interrupt has been called
         Time_Count_INT2=Time_Count_INT2+1.39810133333333; //Then add time counter by total tmr0 overflow -> 1.39810133333333= Total time for tmr0 overflow
         }
         else { //Time count must start from last tmr0 reset value
         Time_Count_INT2=Time_Count_INT2+((65536-Time_Count_INT2_Mem[0])*0.0000213333333333333); //1.39810133333333= Total time for tmr0 overflow
         Time_Count_INT2_Mem[0]=0; //clear time count mem 0
         Time_Count_INT2_Mem[1]=0; //clear time count mem 1
         }
  }

Float TimeCount_Total_INT0=0.0;
#INT_EXT                     // Definition that next line will be associated to External interrupt
void ext_isr(void)           // Function called automaticaly @ Pin_B0 rise edge detection
  {   
       
         Time_Count_INT0_Mem[0]=get_timer0(); //get actual tmr0 value
         FTemp0=Time_Count_INT0_Mem[0]-Time_Count_INT0_Mem[1]; //how many tmr0 counts since last interrupt?
         TimeCount_Total_INT0=Time_Count_INT0+(FTemp0*0.0000213333333333333); //Calculates total pulse time lenght -> Period = 1/((F.Osc/4) / Prescaler)
         Time_Count_INT0_Mem[1]=Time_Count_INT0_Mem[0]; //memorizes current tmr0 value in case a new interrupt happens before tmr0 overflows
         Time_Count_INT0=0;   //Reset Actual "Time counter" for external interrupt INT0
         
         clear_interrupt(INT_EXT);
  }

  Float TimeCount_Total_INT1=0.0;
#INT_EXT1                     // Definition that next line will be associated to External interrupt
void ext_isr1(void)           // Function called automaticaly @ Pin_B1 rise edge detection
  {   
       
         Time_Count_INT1_Mem[0]=get_timer0(); //get actual tmr0 value
         FTemp0=Time_Count_INT1_Mem[0]-Time_Count_INT1_Mem[1]; //how many tmr0 counts since last interrupt?
         TimeCount_Total_INT1=Time_Count_INT1+(FTemp0*0.0000213333333333333); //Calculates total pulse time lenght -> Period = 1/((F.Osc/4) / Prescaler)
         Time_Count_INT1_Mem[1]=Time_Count_INT1_Mem[0]; //memorizes current tmr0 value in case a new interrupt happens before tmr0 overflows
         Time_Count_INT1=0;   //Reset Actual "Time counter" for external interrupt INT1
         
         clear_interrupt(INT_EXT1);
  }
 
  Float TimeCount_Total_INT2=0.0;
#INT_EXT2                     // Definition that next line will be associated to External interrupt
void ext_isr2(void)           // Function called automaticaly @ Pin_B2 rise edge detection
  {   
       
         Time_Count_INT2_Mem[0]=get_timer0(); //get actual tmr0 value
         FTemp0=Time_Count_INT2_Mem[0]-Time_Count_INT2_Mem[1]; //how many tmr0 counts since last interrupt?
         TimeCount_Total_INT2=Time_Count_INT2+(FTemp0*0.0000213333333333333); //Calculates total pulse time lenght -> Period = 1/((F.Osc/4) / Prescaler)
         Time_Count_INT2_Mem[1]=Time_Count_INT2_Mem[0]; //memorizes current tmr0 value in case a new interrupt happens before tmr0 overflows
         Time_Count_INT2=0;   //Reset Actual "Time counter" for external interrupt INT2
         
         clear_interrupt(INT_EXT2);
  }

_________________
Hugo Silva
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Sun Aug 18, 2013 12:23 pm     Reply with quote

The only time 'priority' come into things, is if two interrupt flags are both set when the handler is called. Then the one that is defined first _or_ has the higher 'priority' is processed first.
Generally with a 48MHz clock (12MHIPS), both signals have to be set within a uSec of one another for this ever to apply.

Screaming thing in your posted code - float. Never use floats unless you have to. Even simple things like addition take vastly longer with floats, than with integers. Just set a flag in the timer, and do the FP maths in the main code. Performing FP maths in an interrupt handler, not only takes an age, but also means that interrupts will be disabled in similar maths in the main code.

As a further comment, the PIC 'float' only supports a maximum of 7 digits of resolution. You have a lot of wasted digits in your entries....
younder



Joined: 24 Jan 2013
Posts: 53
Location: Brazil

View user's profile Send private message

PostPosted: Wed Aug 21, 2013 4:41 pm     Reply with quote

I've just eliminated all float variables in my code... I have also tried a flag in the handle with all the math in the main loop, but it gets worse then everything inside the handle... my longest cycle time in the main loop is 66ms... average is 1ms... any help on how to get a better performance by having all math in the main loop?

Code:

Unsigned int32 Cycle_Time=0,Time_Count_INT0=0,Time_Count_INT1=0,Time_Count_INT2=0; // Global variable that contains tmr0 accumulated timer for INT0 - variável global com contador de tempo acumulado (INT0) do Timer 0
Unsigned int16 Cycle_Time_Mem[2]={0,0},Time_Count_INT0_Mem[2]={0,0},Time_Count_INT1_Mem[2]={0,0},Time_Count_INT2_Mem[2]={0,0};
#INT_TIMER0             // Definition that next line will be associated to Timer0 interrupt - linha que define que a próxima função será associada à interrupção do TIMER0
void timer0()           // Function called automaticaly  - esta função não precisará ser chamada. Será executada automaticamente.
  {
         //Pulse time counting for External Interrupt 0
         if (Time_Count_INT0_Mem[0]==0) {  //if no external interrupt has been called
         Time_Count_INT0=Time_Count_INT0+13981013; //Then add time counter by total tmr0 overflow -> 1.3981013=Tempo Total para overflow to contator (TMR0 16bits) = (Tempo de cada incremento * 65536)
         }
         else { //Time count must start from last tmr0 reset value
         Time_Count_INT0=Time_Count_INT0+((int32)(65536-Time_Count_INT0_Mem[0])*213); //0.0000213=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
         Time_Count_INT0_Mem[0]=0; //clear time count mem 0
         Time_Count_INT0_Mem[1]=0; //clear time count mem 1
         }
         
         //Pulse time counting for External Interrupt 1
         if (Time_Count_INT1_Mem[0]==0) {  //if no external interrupt has been called
         Time_Count_INT1=Time_Count_INT1+13981013; //Then add time counter by total tmr0 overflow -> 1.3981013=Tempo Total para overflow to contator (TMR0 16bits) = (Tempo de cada incremento * 65536)
         }
         else { //Time count must start from last tmr0 reset value
         Time_Count_INT1=Time_Count_INT1+((int32)(65536-Time_Count_INT1_Mem[0])*213); //0.0000213=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
         Time_Count_INT1_Mem[0]=0; //clear time count mem 0
         Time_Count_INT1_Mem[1]=0; //clear time count mem 1
         }
         
         //Pulse time counting for External Interrupt 2
         if (Time_Count_INT2_Mem[0]==0) {  //if no external interrupt has been called
         Time_Count_INT2=Time_Count_INT2+13981013; //Then add time counter by total tmr0 overflow -> 1.3981013=Tempo Total para overflow to contator (TMR0 16bits) = (Tempo de cada incremento * 65536)
         }
         else { //Time count must start from last tmr0 reset value
         Time_Count_INT2=Time_Count_INT2+((int32)(65536-Time_Count_INT2_Mem[0])*213); //0.0000213=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
         Time_Count_INT2_Mem[0]=0; //clear time count mem 0
         Time_Count_INT2_Mem[1]=0; //clear time count mem 1
         }
         
         //Cycle Time counting for Main Loop
         Cycle_Time=Cycle_Time+((int32)(65536-Cycle_Time_Mem[0])*213); //0.0000213=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
         Cycle_Time_Mem[0]=0; //clear time count mem 0
         Cycle_Time_Mem[1]=0; //clear time count mem 1
  }

unsigned int32 TimeCount_Total_INT0=0;
#INT_EXT                     // Definition that next line will be associated to External interrupt - linha que define que a próxima função será associada à interrupção externa
void ext_isr(void)           // Function called automaticaly @ Pin_B0 rise edge detection - função executada automaticamente a cada detecção de borda de subida no pino B0.
  {           
         Time_Count_INT0_Mem[0]=get_timer0(); //get actual tmr0 value
         Temp0=Time_Count_INT0_Mem[0]-Time_Count_INT0_Mem[1]; //how many tmr0 counts since last interrupt?
         TimeCount_Total_INT0=Time_Count_INT0+((int32)Temp0*213); //Calculates total pulse time lenght -> 0.0000213=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
         Time_Count_INT0_Mem[1]=Time_Count_INT0_Mem[0]; //memorizes current tmr0 value in case a new interrupt happens before tmr0 overflows
         Time_Count_INT0=0;   //Reset Actual "Time counter" for external interrupt INT0
         clear_interrupt(INT_EXT);
  }
   
unsigned int32 TimeCount_Total_INT1=0;
#INT_EXT1                     // Definition that next line will be associated to External interrupt
void ext_isr1(void)           // Function called automaticaly @ Pin_B1 rise edge detection
  {         
         Time_Count_INT1_Mem[0]=get_timer0(); //get actual tmr0 value
         Temp0=Time_Count_INT1_Mem[0]-Time_Count_INT1_Mem[1]; //how many tmr0 counts since last interrupt?
         TimeCount_Total_INT1=Time_Count_INT1+((int32)Temp0*213); //Calculates total pulse time lenght -> 0.0000213=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
         Time_Count_INT1_Mem[1]=Time_Count_INT1_Mem[0]; //memorizes current tmr0 value in case a new interrupt happens before tmr0 overflows
         Time_Count_INT1=0;   //Reset Actual "Time counter" for external interrupt INT1
         clear_interrupt(INT_EXT1);
  }

unsigned int32 TimeCount_Total_INT2=0;
#INT_EXT2                     // Definition that next line will be associated to External interrupt
void ext_isr2(void)           // Function called automaticaly @ Pin_B2 rise edge detection
  {       
         Time_Count_INT2_Mem[0]=get_timer0(); //get actual tmr0 value
         Temp0=Time_Count_INT2_Mem[0]-Time_Count_INT2_Mem[1]; //how many tmr0 counts since last interrupt?
         TimeCount_Total_INT2=Time_Count_INT2+((int32)Temp0*213); //Calculates total pulse time lenght -> 0.0000213=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
         Time_Count_INT2_Mem[1]=Time_Count_INT2_Mem[0]; //memorizes current tmr0 value in case a new interrupt happens before tmr0 overflows
         Time_Count_INT2=0;   //Reset Actual "Time counter" for external interrupt INT2
         clear_interrupt(INT_EXT2);       
  }

_________________
Hugo Silva
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed Aug 21, 2013 5:01 pm     Reply with quote

whats your #use delay statement ?

whats your TIMER setup statement ?
prescalar of interest as you say 16 bits.....

and whats this about ?
Code:

+13981013
younder



Joined: 24 Jan 2013
Posts: 53
Location: Brazil

View user's profile Send private message

PostPosted: Wed Aug 21, 2013 8:06 pm     Reply with quote

[quote="asmboy"]whats your #use delay statement ?

Code:
#use delay (clock=48000000)


whats your TIMER setup statement ?
prescalar of interest as you say 16 bits.....

Code:

setup_timer_0 (T0_INTERNAL | T0_DIV_256 );
enable_interrupts(INT_TIMER0);

setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1)


and whats this about ?
Code:

+13981013


1.3981013 seconds is the total time for Timer0 overflows (65536*0.0000213 sec.) -> 0.0000213=time of each increment
_________________
Hugo Silva
temtronic



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

View user's profile Send private message

PostPosted: Thu Aug 22, 2013 9:19 am     Reply with quote

hmm...

You might consider simplfying your code by getting one sensor working right,say the RPM one, as it has the highest frequency.

If you 'sync' the others to be read at the same time,then you only need ONE ISR( RPM in this case).

Then use fast integer math to do all the required calculation in 'main' to display the results.

just another way to do it...

hth
jay
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