![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
PIC24EP512GP806 external interrupt max speed |
Posted: Wed Mar 15, 2017 11:50 am |
|
|
Device: PIC24EP512GP806
Compiler: 5.026
Hello again,
Quick question on external interrupts...
My PCB is already done and working and quite small so I want to avoid any type of hardware hack to try it myself if I can to avoid breaking something else.
One of my external interrupts tied to a CN pin is an 8kHz clock. The reason I am using this interrupt is that I need to detect on both edges... but if I was to tie it to a standard EXTx interrupt, I could simply change the H_to_L and L_to_H bit depending on how I need it to trigger.
But the question: can normal EXTx interrupts also trigger on 8kHz?
How about 16kHz?
Thanks,
Benoit |
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Wed Mar 15, 2017 12:11 pm |
|
|
Depends what else you have going on and what your clock speed is. In general, you're probably looking at ~80 instructions minimum just to enter and exit the ISR. If your processor is running at 40 MIPS, a 16kHz signal is a 2500 cycle period, or ~1250 cycles if it's a 50% duty cycle and you want to detect rising and falling edges.
On paper, your processor is probably more than capable of handling that signal but it really depends on everything else you presently have it doing. |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Mar 15, 2017 12:34 pm |
|
|
My external crystal is 36.864MHz running the PLL at 129.024 MHz.
The MCU is doing a million other things and the entire circuit is interrupt driven (UART, DMA, external interrupts, timers etc). The 8kHz signal tied to a CN interrupt works just fine because it is alone _at the moment_ using the CN interrupt.
But since I need to potentially add two more 'slow' external interrupts and given that the 8kHz is fast and constant and triggers 16K interrupts per seconds (every transition), then it is only logical to keep the 8kHz signal alone on its own interrupt (e.g. EXTx) and have all the other ones use the CN interrupt so that when that interrupt gets triggered, the MCU just needs to read which pin generated the interrupt.
On the other hand, if I share the CN interrupt between the 8kHz signal and another slower type of interrupt from an external sensor, then both signals could potentially trigger the CN interrupt and cause problems... You see, the 8kHz interrupt is for timing something precise and if at some point it gets triggered twice within a low or a high transition (one interrupt from the real 8kHz signal, one from the other interrupt), this will cause problems.
So this leads me back to if it is possible to trigger an EXTx interrupt with 8kHz. I would be tempted to say 'yes' but if someone knows the answer before I start butchering my nice circuit considering it is all 0402 parts with 0.008" traces, then that would be totally awesome!
Thanks again,
Benoit |
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Wed Mar 15, 2017 12:37 pm |
|
|
If there's any possibility of using DMA to help handle that external interrupt, look into doing so. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Wed Mar 15, 2017 12:54 pm |
|
|
What does your interrupt actually have to do?.
If it simply needs counting, remember this can be done without involving an interrupt at all.
If it is transferring something, then as Newguy says use DMA.
How short might the quickest pair of edges be?. If you are recording (say) a timer on the edges, then the chip can buffer four edge times. |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Thu Mar 16, 2017 7:34 pm |
|
|
I have external sensors that trigger an interrupt when it senses 'whatever' that sensor is meant to detect. For instance, I have an accelerometer that triggers an ON interrupt on one pin when motion is detected and triggers an OFF interrupt on a second pin when motion stops. These are on EXT0 and EXT1 for instance. Then I have other interrupts like that on EXT2, EXT3 and EXT4 from other sensors.
Then I need a 6th interrupt which is where I tied my 8kHz signal and for this one, I used the CN interrupt. This is perfect because it triggers an interrupt on every change and it just so happens that my 8kHz signal must trigger sometimes on the low edge, sometimes on the high edge. The edge it must trigger on depends on other factors inside the MCU. This clock is synced with realtime data that the MCU is sampling, buffering and processing later-on.
But now I would like to add two extra external sensors in the next PCB revision. Given the cost of having PCBs fabricated, I must make sure that the changes work. I currently have only one circuit of the current revision assembled and I want to avoid butchering it for testing because it's all 0402 (and smaller) parts with 0.008" traces.
For the two new interrupts I need, I cannot make them CN interrupts as well because when they trigger, they could potentially cause false triggers for the 8kHz interrupt and vice-versa. The 8kHz really needs to be alone on its own interrupt.
So this leaves me with using an EXTx interrupt for the 8kHz clock and simply toggle the L_TO_H and H_TO_L flag to make it trigger on whichever edge I need it to trigger on. Now the only thing that remains to know is if EXTx interrupts can trigger on an 8kHz signal.
Ben |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Fri Mar 17, 2017 2:55 am |
|
|
The CN interrupt, is an interrupt on pin(s) changing. As you say, you then have the problem of distinguishing which pin changed. However that isn't actually that hard to do. If the pins are all on the same port, you only need to read the port, XOR with the value that was on the port when it was last read, AND with a pattern corresponding to the bits you actually want to test, and any bit 'on' in the result, is a bit that has changed. Store the port value that was read at this point. It won't miss values, since it resets it's latch at the moment it is read. So it is perfectly capable of handling simultaneous, or overlapped changes on all pins selected. The compiler actually supplies a function to do the XOR and save (input_change). So code like:
Code: |
//assuming you use (say) B0 to B3 as 'change' interrupts
#define CHANGE_MASK 0x0F //to check pins B0 to B3
//then in the interrupt handler
#INT_CNI
void port_changed(void)
{
int16 changes;
changes=input_change_b() & CHANGE_MASK;
if (bit_test(changes,0))
{
//code for B0
}
if (bit_test(changes,1))
{
//code for B1
}
if (bit_test(changes,2))
{
//code for B2
}
if (bit_test(changes,3))
{
//code for B3
}
}
//Then when setting up the main
int16 dummy;
dummy=input_change_b(); //this initialises the latch
clear _interrupts(INT_CNI);
enable_interrupts(INT_CNI);
enable_interrupts(INTR_GLOBAL);
|
Now this is actually much more efficient than coding multiple separate interrupts. Only one set of register saves/restores, and the code will respond to any other pins that have changed between the instant the port was last read (on the last interrupt), and where it is read here. Even if the pin changes just one cycle after it is read, it'll just interrupt again.
If you must use separate interrupts, then the input capture interrupts. These work by 'capturing' a timer value, when the pin changes. CAPTURE_EE says to capture 'every edge'. INTERRUPT_EVERY_CAPTURE says to interrupt every time a capture occurs. The exact time when the even occurred will be available to you if you read the stored capture value (get_capture), but to simply interrupt you don't have to use this.
Honestly just checking what bit triggered the change is by far the better code for what you describe. The interrupt capture solution is the better, if you need to know exactly 'when' a particular edge triggered. Using the standard interrupts brings the problem that you could lose edges if a second one occurs between the interrupt 'triggering', and you leaving it's handler (which could be quite a long time if another interrupt has also triggered, and is handled 'first'...).
Note that it is also much more efficient to just code the four separate tests discreetly, rather than trying to be 'smart' and use a loop. The compiler can code a single bit test and branch as a single instruction. So if it arrives and just one bit is set, the extra tests add almost nothing to the code.... |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Mar 17, 2017 4:46 am |
|
|
Hi TTelmah,
Thanks for all the details, again, very appreciated.
I've thought also about the way you explained where you read each bit separately in the CN interrupt.
But given that I will have to do a PCB re-spin anyhow because I have one mistake on the PCB and a few more requirements were handed-down to me, then that's why I'm saying that I might as well take the opporunity to simply put the 8kHz signal on its own interrupt then I can use the CN interrupt for the two new interrupts I want to add.
But all feedback is taken in consideration and will be discussed at the next meeting with colleagues.
Thanks for all the help.
Benoit |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Fri Mar 17, 2017 5:31 am |
|
|
That makes sense, given the different 'nature' of these interrupts. ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|