Multiple interrupts in one port

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hello everyone and good afternoon, I'm trying to set 6 interruptions in the "Port 0", the problem that I have is that I don't have too much idea of how to set one interruption for a specific pin to trigger when sensed a falling edge (they are set as pull-up resistive input pins) and another interruption for the same pin to sensed the rising edge, in other words, the pressing of a push button. As far as I know when we are talking about a component pin (several pins triggered by one dedicated interrupt for that specific port ), we need to use the function "<name of the port block>_ClearInterrupt()" to get the value from the pin register, that tells us which pin triggered the interrupt (I have already done that), but my main problem is with the rising and falling edges that I haven't managed to make it wor. 

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Here is how I setup three push buttons on the same port:

   

/****Call once in main****/
    Button_ISR_StartEx(BtnInterrupt_ISR);//setup button edge interrupt ISR

   


//Called every button edge to have unit start debouncing the buttons
CY_ISR(BtnInterrupt_ISR) {
    Button_ClearInterrupt();//reset interrupt for the entire port

   

/**Do code based edge interrupt here. Will trigger for both rising and fall edges**/
}

View solution in original post

10 Replies
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Here is how I setup three push buttons on the same port:

   

/****Call once in main****/
    Button_ISR_StartEx(BtnInterrupt_ISR);//setup button edge interrupt ISR

   


//Called every button edge to have unit start debouncing the buttons
CY_ISR(BtnInterrupt_ISR) {
    Button_ClearInterrupt();//reset interrupt for the entire port

   

/**Do code based edge interrupt here. Will trigger for both rising and fall edges**/
}

Anonymous
Not applicable

Hi e.pratt_1639216,

I'm trying to add four switch interrupts to Port 3 as you have done in the example screen shot.

I want to use Pin 49, 51,52, 53 in Port 3 on CY8C4248LQI-BL583

I'm getting error like below

Error: fit.M0007: Invalid pin assignment. ''49,51,52,53' is not a valid port pin ID. Enter a valid port pin ID that exists on the current package to start the assigment at (valid format: '2').' Either press Esc to cancel the edit or enter a valid assignment.

0 Likes
Anonymous
Not applicable

It looks like the format of your pin assignment might be off?

Try '49','51','52','53' instead?

Otherwise, for the example I posted above, I used the Pin Component on the TopDesign.cysch page to create the 3-pin input, and then assigned the pins to the input in the Design01.cydwr ("PINS") page.

0 Likes
Anonymous
Not applicable

It worked, apparently the PIN assignment should be contiguous in PSoC 4.

We changed the Hardware design to Pin 50, 51, 52, 53 and things work well.

Thanks for your support.

0 Likes
Anonymous
Not applicable

Doh; I've run into that before and should have noticed the numbers skipping 50 >.<

Well, glad you got it working now

0 Likes
Anonymous
Not applicable

Hello once again "e.pratt_1639216"! thank you very much, that was the function I was looking for, and just for the record, that function has a return value and that is the data register that contains the information of which pin in the port was the one that triggered the interruption and with an AND bit operation like this:  

   

/*Inside the interruption function
pinTrigger=Button_ClearInterrupt();

   

if(0x00==pinTrigger & (port_Read()))

   

{/*Code for Falling Edge */}

   

else {

   

/*code for Rising Edge*/

   

}

   

Note: This works as long as the pins are set Resistive pull-ups, if they are not the "if" and "else" statement comparator values must change.

   

and with just a simple "switch" statement that that has as an argument the variable portTrigger, you can have the next code

   

switch (portTrigger){

   

case 0x01:

   

break;

   

case 0x02:

   

break;

   

case 0x04

   

break;

   

......

   

}

   

you can be sure of which pin in the port did that interruption

Anonymous
Not applicable

Interesting, I guess I never bothered to check the return value 🙂

   

Being used to hardware that didn't debounce the edges of GPIO, I assumed that the port would bounce during/after triggering an interrupt to wakeup the unit, so I setup a debounce timing routine to figure out what edge (rising/falling), and which button pins were being changed. I'll probably play around with the approach you are doing sometime to see how reliable it is 🙂

   

I'm glad you figured it out though!

0 Likes
Anonymous
Not applicable

Thank you very much! yes do it!, what I like of that solution is that you only need one simple bit-operator, the information of which pin triggered the INT and the Port bits status and you can set one block of codes for each pin with the switch statement 🙂

0 Likes
Anonymous
Not applicable

I am new to the forum but have been working with Cypress for a while.  So I am a bit (so to speak) confused here
in the snippet of code shown by adrian_2306846. 

   

First on de-bounce.  I am not sure this eliminates de-bounce since you are reading the state of the pin for use in your
process tree  From my experience with Cypress (and many other processor) GPIO pins and interrupts, and the
the processing speed of one of these processors is such that the state of that pin/line can easily bounce around before
especially if it is human-activated.  On a note, if you run a 24MHz clock (like ECO) and have a 4-step pipeline, you
would be able to execute 6000 instructions in a millisecond.  This means the time it takes from entering your isr to the
time you read the state of the pin is VERY short and that pin may not have settled.  I do suggest de-boucing the pin.

   

Next, I just want to make sure there is a mistake in how the pin state is being interpreted.  In all of my Cypress firmware
that deals with edge-interrupts and the resulting pin state and which is working seems to be reversed from the code snippet.
If an interrupt is caused by a falling edge (with a resistive pull-up and ana initial state of high), the resulting pin state would
low and the read would return a zero.  It would be opposite on a rising edge.  The comments based on the read result
seem to reverse this pattern.

   

I only bring this up to make sure I am not supposed to do things differently on a Cypress chip and their GPIO pins than
all of the other processors I have worked on.  If this is so and this snippet is correct, I will proceed to invert my code.

   

Thanks all and take care.  🙂

0 Likes
Anonymous
Not applicable

The cypress pins that have an edge-triggered functionality tend to do some sort of analog D-flip-flop edge filtering from what I've seen, and thus as adrian said above, it will work without debouncing (depending on what kind of input you are using). I would agree that you shouldn't trust it not to bounce, and thus I would implement a debouncing on the input as well, but I have seen pretty stable results with the edges from testing (using rubber conductive buttons pressed by user).

   

That said, I believe the method that he is using for detecting the edge direction seems fine to me. The pinTrigger variable will be set to 1 for each bit that triggered and edge interrupt (will almost never have more than 1 in most use cases), and the port_Read() will return 1 for each pin that is currently set High. Thus, when you & together the edge with the current state, then the result will be 1 IFF at least one pin is a rising edge, and if no pins triggered a rising edge, then it will process a falling edge.

   

Adrian does have the comments backwards for the rising and falling edges. The idea itself is effective however, as it allows you to do code based on which direction the edge is triggering. For my own application, I implemented a duality approach, where I start a timing routine on a trigger from the inputs, and then debounced for a minimum count before checking if the pins were stable. Once the pins stabilized after the minimum count, I then did an action based on the new stabilized value I read compared with the previously read stabilized value (I stored the previous value in a register). This allowed me to debounce multiple pins, debounce them for adjustable length/timing, and to have the debouncing be separate from a pin edge trigger (It would be a bummer to only be debouncing when the pin triggers and edge 🐵

   

Since Adrian doesn't need/want a higher fidelity debouncing routine, he's gone ahead with the simple edge-triggered code directly in the ISR, but for you Thunderboy, depending on your requirements, you should probably do debouncing, and only use the edge-trigger to start the debouncing routine/method.

   

Here's some pseudocode for the debouncing architecture I used:

   

Button_Edge_ISR() {

   

Start_Debounce_Routine();//Check to make sure it isn't already running so that hardware isn't call to start twice

   

}

   

Timer_Tick_ISR() {

   

Increment_Debounce_Count();

   

Debounce_Last_Ten_Values();

   

if(Debounce_Count > 10 && Current_State_is_Valid()) {

   

//Done debouncing, pass value to main application

   

Stop_Debounce_Routine();

   

}

   

}