External interrupt PIC18F

Thread Starter

raychar

Joined Nov 8, 2011
82
Hello,

I have sucessive pulses inputing to the external interrupt of PIC18F452, the time between them are quite short and don't know if the IC can catch them all.

Does anybody know how much shortest time this IC can handle between two pulses in the external interrupt? The interrupt subroutine contains only two instructions before clear the corresponding flag.

Thanks in advance.
Raychar
 

joeyd999

Joined Jun 6, 2011
4,231
The PIC 18F architecture is such that it can only manage 1 interrupt at a time (2 if using priority interrupts).

Additionally, there is only one interrupt flag for each of the external ints, so you must clear the proper flag before another interrupt can be captured.

Generally speaking, the rate at which you can capture ints is going to be dictated by how much time you spend in the interrupt routine (including 2 or 3 instruction cycle latency + 2 instruction cycle RETFIE). And this is *only* if you have no other high-priority interrupts, or if you are not using priority and have other interrupts to handle.

To insure proper capture of all external ints, make sure your interrupt routine is as short as possible. Do only the bare minimum processing necessary, and get out. Use high priority, and the fast return stack.

And clear your interrupt flag early. This will give you the opportunity to capture the next interrupt while still processing the old one. But if this happens too often, you will not process all ints.
 

Thread Starter

raychar

Joined Nov 8, 2011
82
Thanks for your detailed reply.

There are two inputs and they do not have the pulses at the same time. So, they are brought to INT0 and INT1, and, the subroutines are as following. Can you advise comments or calculation of processing times for them?

/*--------------------------------------------------*/
void interrupt HI_ISR()
{
if(INT0IF==1)
{
Sum=Sum-1;
INT0IF=0;
}
if(INT1IF==1)
{
Sum=Sum+1;
INT1IF=0;
}
}
/*--------------------------------------------------*/

For me, the estimation is: Sum=Sum-1 is 2 instr. cycle, INT0IF=0 is 1 instr. cycle, +(including 2 or 3 instruction cycle latency + 2 instruction cycle RETFIE) =
total 8 instr. cycles.

For 20MHz oscilation used, i.e. 0.2us per instr. cycle, so 0.2usx8=1.6us. For handling 2 interrupts, it needs to take 1.6usx2=3.2us before to process another interrupts. Is it correct, could have any advise?

Thanks,
Raychar
 

joeyd999

Joined Jun 6, 2011
4,231
Thanks for your detailed reply.

There are two inputs and they do not have the pulses at the same time. So, they are brought to INT0 and INT1, and, the subroutines are as following. Can you advise comments or calculation of processing times for them?

/*--------------------------------------------------*/
void interrupt HI_ISR()
{
if(INT0IF==1)
{
Sum=Sum-1;
INT0IF=0;
}
if(INT1IF==1)
{
Sum=Sum+1;
INT1IF=0;
}
}
/*--------------------------------------------------*/

For me, the estimation is: Sum=Sum-1 is 2 instr. cycle, INT0IF=0 is 1 instr. cycle, +(including 2 or 3 instruction cycle latency + 2 instruction cycle RETFIE) =
total 8 instr. cycles.

For 20MHz oscilation used, i.e. 0.2us per instr. cycle, so 0.2usx8=1.6us. For handling 2 interrupts, it needs to take 1.6usx2=3.2us before to process another interrupts. Is it correct, could have any advise?

Thanks,
Raychar
Depends on the implementation of your compiler. I do this stuff in asm so I know for sure.

Question to C gurus: does 'sum=sum+1' resolve the same as 'sum++'?

One benefit of the way you wrote the code: if both ints occur simultaneously, you only get 1 latency and 1 RETFIE penalty. Good coding.

I can't see anyway to make it faster, aside from coding in asm to be certain of instruction cycles.

PS -> in the future, use code tags...easier on the eyes.
 

joeyd999

Joined Jun 6, 2011
4,231
I checked a 18F datasheet: interrupt latency is 3 to 4 Tinst, not 2-3. Sorry!
 

t06afre

Joined May 11, 2009
5,936

Thread Starter

raychar

Joined Nov 8, 2011
82
Hello,

The assembly listing window for the about subroutine is copied as below. And I wrote the number of cycle for each. By summng up, the total is 32(41) cycles. For 0.2us per cycle, meaning 6.4(8.2)us. Please correct me if I am wrong.

As I changed to using C from assembly, I almost forget most of them and thinking that it's hard to change back.

Thanks,
Raychar

249: void interrupt HI_ISR()
250: {
0A34 FFFF NOP ;1 cycle
0A36 D015 BRA 0xa62 ;1(2) cycle
251:
252: if(INT0IF==1) //Downward
0A38 A2F2 BTFSS 0xff2, 0x1, ACCESS ;1(2) cycles
0A3A D001 BRA 0xa3e ;1(2)
0A3C D001 BRA 0xa40 ;1(2)
0A3E D005 BRA 0xa4a ;1(2)
253: {
254: Sum=Sum-1; //Sum is from -32768 to +32767 or -68mm to +68mm
0A40 0100 MOVLB 0 ;1
0A42 0790 DECF 0x90, F, BANKED ;1
0A44 0EFF MOVLW 0xff ;1
0A46 2391 ADDWFC 0x91, F, BANKED ;1
255: INT0IF=0;
0A48 92F2 BCF 0xff2, 0x1, ACCESS ;1
256: }
257: if(INT1IF==1) //Upward
0A4A A0F0 BTFSS 0xff0, 0, ACCESS ;1(2)
0A4C D001 BRA 0xa50 ;1(2)
0A4E D001 BRA 0xa52 ;1(2)
0A50 D006 BRA 0xa5e ;1(2)

258: {
259: Sum=Sum+1;
0A52 0100 MOVLB 0 ;1
0A54 0E01 MOVLW 0x1 ;1
0A56 2790 ADDWF 0x90, F, BANKED ;1
0A58 0E00 MOVLW 0 ;1
0A5A 2391 ADDWFC 0x91, F, BANKED ;1
260: INT1IF=0;
0A5C 90F0 BCF 0xff0, 0, ACCESS ;1
261: }
262: }
0008 EF32 GOTO 0xa64 ;2
000A F005 NOP ;1
000C FFFF NOP ;1
000E FFFF NOP ;1
0010 FFFF NOP ;1
0012 FFFF NOP ;1
0014 FFFF NOP ;1
0016 FFFF NOP ;1
0A5E 0011 RETFIE 0x1 ;2
263: /*--------------------------------------------------*/
 

joeyd999

Joined Jun 6, 2011
4,231
Rich (BB code):
249:               void interrupt HI_ISR()
250:               {
  0A34    FFFF     NOP                                    ;1 cycle
  0A36    D015     BRA 0xa62                           ;1(2) cycle
251:               
252:                if(INT0IF==1)  //Downward
  0A38    A2F2     BTFSS 0xff2, 0x1, ACCESS      ;1(2) cycles
  0A3A    D001     BRA 0xa3e                           ;1(2)
  0A3C    D001     BRA 0xa40                           ;1(2)
  0A3E    D005     BRA 0xa4a                           ;1(2)
253:                {
254:                 Sum=Sum-1;   //Sum is from -32768 to +32767 or -68mm to +68mm
  0A40    0100     MOVLB 0                              ;1
  0A42    0790     DECF 0x90, F, BANKED            ;1
  0A44    0EFF     MOVLW 0xff                          ;1
  0A46    2391     ADDWFC 0x91, F, BANKED       ;1
255:                 INT0IF=0;
  0A48    92F2     BCF 0xff2, 0x1, ACCESS         ;1
256:                }
257:                if(INT1IF==1)  //Upward
  0A4A    A0F0     BTFSS 0xff0, 0, ACCESS        ;1(2)
  0A4C    D001     BRA 0xa50                          ;1(2)
  0A4E    D001     BRA 0xa52                          ;1(2)
  0A50    D006     BRA 0xa5e                          ;1(2)

258:                {
259:                 Sum=Sum+1;
  0A52    0100     MOVLB 0                              ;1
  0A54    0E01     MOVLW 0x1                          ;1
  0A56    2790     ADDWF 0x90, F, BANKED         ;1
  0A58    0E00     MOVLW 0                             ;1
  0A5A    2391     ADDWFC 0x91, F, BANKED       ;1
260:                 INT1IF=0;
  0A5C    90F0     BCF 0xff0, 0, ACCESS             ;1
261:                }
262:               }
  0008    EF32     GOTO 0xa64                          ;2
  000A    F005     NOP                                     ;1
  000C    FFFF     NOP                                     ;1
  000E    FFFF     NOP                                     ;1
  0010    FFFF     NOP                                     ;1
  0012    FFFF     NOP                                     ;1
  0014    FFFF     NOP                                     ;1
  0016    FFFF     NOP                                     ;1
  0A5E    0011     RETFIE 0x1                           ;2
263:               /*--------------------------------------------------*/
Yet another reason why I despise compilers for embedded apps...
 

AlexR

Joined Jan 16, 2008
735
Nothing wrong with C compilers per se. Its just the compilers marketed by Microchip that disable optimisation until you come up with the cash that make an utter hash of the code.

But back to the problem. If you are worried about the time it takes to service the interrupt maybe you should consider upping your clock rate. The PIC18F452 will run at 40MHz if you drop the crystal down to to 10MHz and turn on the PLL.
 

thatoneguy

Joined Feb 19, 2009
6,349
Yet another reason why I despise compilers for embedded apps...
He's running a free version that doesn't do optimization. Hi-Tech has given C for PIC a bad name because they want their $1500 license.

Try BoostC from sourceboost to see how it goes, there won't be half the junk you see in the compiled code.
 

Thread Starter

raychar

Joined Nov 8, 2011
82
Hello,

I think if the part of program that is time-concerned, it can be written in assembly instead of the rest of program that is in C language. Can anybody how to write this interrupt subroutine in assembly language? What is BRA.?...

Thanks,
Raychar
 

Thread Starter

raychar

Joined Nov 8, 2011
82
Yes, I already run at maximum 40MHz with PLL now, thanks. I still want this routine in assembly language. Can anyone help to do it? How to use branch command 'BRA'? Thanks, Raychar
 

joeyd999

Joined Jun 6, 2011
4,231
Yes, I already run at maximum 40MHz with PLL now, thanks. I still want this routine in assembly language. Can anyone help to do it? How to use branch command 'BRA'? Thanks, Raychar
Read the datasheet, please. You'll find the info under 'Instruction Set'.
 
Top