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

Understanding Interrupt-On-Change

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



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

Understanding Interrupt-On-Change
PostPosted: Wed Apr 30, 2014 10:58 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 30, 2014 11:59 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 30, 2014 12:12 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 30, 2014 12:19 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 30, 2014 12:31 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 30, 2014 1:01 pm     Reply with quote

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