View previous topic :: View next topic |
Author |
Message |
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
Understanding Interrupt-On-Change |
Posted: Wed Apr 30, 2014 10:58 am |
|
|
I am using the interrupt-on-change feature and it works fine. But I don't understand the asm code generated by the compiler (v5.025):
Code: |
.................... enable_interrupts(INT_RA1_L2H);
00B9: BSF 0B.3
00BA: MOVLB 07
00BB: BSF 11.1
00BC: BCF 12.1
.................... enable_interrupts(INT_RA1_H2L);
00BD: BSF 0B.3
00BE: BSF 12.1
00BF: BCF 11.1
|
I am using both the Low-To-High and High-To-Low interrupts for pin A1. And it works. But I don't understand the asm code above.
Function Register 11 is the IOCAP (low-to-high) register, and Register 12 is the IOCAN (high-to-low) register. And the enable for pin A1 is bit 1 of both registers.
What I don't understand is why, when the low-to-high interrupt is enabled, the code also disables the high-to-low interrupt, and when the high-to-low interrupt is enabled, the code also disables the low-to-high interrupt. It appears that only one of the two interrupts can be enabled at a time, yet both edges cause an interrupt. How does that work? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Wed Apr 30, 2014 11:59 am |
|
|
While I don't use those features, the code you show is 100% correct for what you've requested.
first you...
enable_interrupts(INT_RA1_L2H);
the assembler code shows that indeed the low to high edge interrupt is configured
then you...
enable_interrupts(INT_RA1_H2L);
the assembler code shows that now you've asked for the high to low edge.
What I gather from your post is that you want BOTH the H2L AND L2H edges to generate interrupts. That configuration requires you to specify BOTH within one enable_interrupt(......options.....)
I suggest you press F11 while your project is open,look for the 'enable_interrupts() function, open it and see what the correct syntax is.
hth
jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 30, 2014 12:12 pm |
|
|
Quote: | But I don't understand the asm code generated by the compiler |
Go to Project Build options and set the .LST file format to Symbolic mode.
Then you'll see register names instead of hex addresses.
Quote: |
What I don't understand is why, when the low-to-high interrupt is enabled,
the code also disables the high-to-low interrupt. |
The function calls are not cumulative. Each one only allows the selected edge.
Example:
Code: |
.................... enable_interrupts(INT_RA1_L2H);
0008: BSF INTCON.IOCIE
0009: MOVLB 07
000A: BSF IOCAP.1
000B: BCF IOCAN.1
....................
.................... enable_interrupts(INT_RA1_H2L);
000C: BSF INTCON.IOCIE
000D: BSF IOCAN.1
000E: BCF IOCAP.1
.................... |
If you do want both edges, then call it with the INT_RA1 parameter.
Example:
Code: | .................... enable_interrupts(INT_RA1);
000F: BSF INTCON.IOCIE
0010: BSF IOCAP.1
0011: BSF IOCAN.1
.................... |
|
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Wed Apr 30, 2014 12:19 pm |
|
|
Thank you. That was helpful. Or'ing the two enables in the same call generated the code I expected.
I did go through the documentation and the example programs, and none of them suggested Or'ing enable flags together in a common call. In fact, the manual shows as examples, multiple calls to enable_interrupts(), each with a single interrupt source. So that's how I wrote my code. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 30, 2014 12:31 pm |
|
|
In the general case, OR'ing the interrupt enable constants is not
recommended. Sometimes it is possible, but if the register addresses
are different for each interrupt type, OR'ing will fail. I never do it. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 30, 2014 1:01 pm |
|
|
Let's look at the code.
Here's the test program. It will show us the .LST file code for individual
edges, and for your OR'ing method, and for the INT_RA1 parameter
Code: |
#include <12LF1552.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
//====================================
void main(void)
{
enable_interrupts(INT_RA1_L2H);
enable_interrupts(INT_RA1_H2L);
enable_interrupts(INT_RA1_L2H | INT_RA1_H2L);
enable_interrupts(INT_RA1);
while(1);
} |
Here we see that the individual parameters select the specified edge
and disable the other edge, as expected:
Code: | .................... enable_interrupts(INT_RA1_L2H);
0008: BSF INTCON.IOCIE
0009: MOVLB 07
000A: BSF IOCAP.1
000B: BCF IOCAN.1
....................
.................... enable_interrupts(INT_RA1_H2L);
000C: BSF INTCON.IOCIE
000D: BSF IOCAN.1
000E: BCF IOCAP.1
....................
|
BSF means it's enabled. BCF means it's disabled. 'N' means the negative
edge and 'P' is the positive edge in the register names above.
Here, your OR'ing method enables both edges. But OR'ing is not specified
in the 12LF1552.h file as a correct method of using the enable_interrupts()
function:
Code: |
.................... enable_interrupts(INT_RA1_L2H | INT_RA1_H2L);
000F: BSF INTCON.IOCIE
0010: BSF IOCAP.1
0011: BSF IOCAN.1
....................
|
Below, we're using the INT_RA1 parameter from the 12LF1552.h file
and it enables both edges, producing the same code as the OR'ing method.
This is the correct way to do it:
Code: |
.................... enable_interrupts(INT_RA1);
0012: BSF INTCON.IOCIE
0013: BSF IOCAP.1
0014: BSF IOCAN.1
|
|
|
|
|