Interrupts in C
The IO Pi Plus is a 32 channel MCP23017 GPIO expander for the Raspberry Pi
27/03/2020
Posted by:
Robspalu
I am having problems with interrupts in C.
I have modified the demo-iopiread2 module, to use interrupts, but I dont seem to see them. A previous user also asked about interrupts some time back, and he seemd to use WiringPiISR?, which seemed a bit odd.
Below is the modified demo code:
int main(int argc, char **argv){
char isr1 = 0;
char isr2 = 0;
setvbuf (stdout, NULL, _IONBF, 0); // needed to print to the command line
IOPi_init(0x20); // initialise one of the io pi buses on i2c address 0x20, default address for bus 1
set_port_direction(0x20,0, 0xFF); // set bank 0 to be inputs
set_port_direction(0x20,1, 0xFF); // set bank 1 to be inputs
set_port_pullups(0x20, 0, 0xFF); // enable internal pullups for bank 0
invert_port(0x20,0,0xFF); // invert output so bank will read as 0
set_port_pullups(0x20, 1, 0xFF); // enable internal pullups for bank 0
invert_port(0x20,1,0xFF); // invert output so bank will read as 0
set_interrupt_defaults(0x20,0,0);// Set Interrupt default Port 0
set_interrupt_defaults(0x20,1,0);// Set Interrupt default Port 1
set_interrupt_type(0x20,0,0);// Set Interrupt type to state change Port 0
set_interrupt_type(0x20,1,0);// Set Interrupt type to state change Port 1
set_interrupt_on_port(0x20,0,0);// Enable Interrupts Port 0
set_interrupt_on_port(0x20,1,0);// Enable Interrupts Port 1
//reset_interrupts(0x20);
while (1){
clearscreen();
isr1 = read_interrupt_status(0x20,0); // Read Port 0 Interrupt status
isr2 = read_interrupt_status(0x20,1); // Read Port 1 Interrupt status
printf("ISR Port 0 %x \n", isr1); // Interrupt Status Port 0
printf("Port 0 %x \n", read_port(0x20,0)); // grounding a pins 1 to 8 will change the value
printf("ISR Port 1 %x \n", isr2); // Interrupt Status Port1
printf("Port 1 %x \n", read_port(0x20,1)); // grounding a pins 1 to 8 will change the value
usleep(200000); // sleep 0.2 seconds
}
return (0);
Can anyone spot the problem
Thanks Dave
27/03/2020
Posted by:
andrew
The set_interrupt_on_port needs a value of 0xFF for the third parameter to enable the interrupt for all pins. Where you used a value of 0 you were disabling the interrupts instead of enabling them.
Try changing the two set_interrupt_on_port() lines to the code below.
set_interrupt_on_port(0x20,0,0xFF);// Enable Interrupts Port 0
set_interrupt_on_port(0x20,1,0xFF);// Enable Interrupts Port 1
27/03/2020
Posted by:
Robspalu
Thanks for the suggestion, unfortunatley still no value for interrupt status reported when input state changes, but read_port correctly shows status.
Any other suggestions ?
Thanks Dave
27/03/2020
Posted by:
andrew
I tried your code and the interrupt is triggering but where your loop is repeating every 0.2 seconds it only flashed up on the screen for a fraction of a second before disappearing again so it was easy to miss.
I have translated the interrupt demo from our python library to C.
#include
#include
#include
#include
#include "ABE_IoPi.h"
void clearscreen ()
{
printf("\033[2J\033[1;1H");
}
int main(int argc, char **argv)
{
setvbuf(stdout, NULL, _IONBF, 0); // needed to print to the command line
// initialise one of the io pi buses on i2c address 0x20, default address for bus 1
IOPi_init(0x20);
// Set all pins on the IO bus to be inputs with internal pull-ups enabled.
set_port_pullups(0x20, 0, 0xFF);
set_port_pullups(0x20, 1, 0xFF);
set_port_direction(0x20, 0, 0xFF);
set_port_direction(0x20, 1, 0xFF);
// Invert both ports so pins will show 1 when grounded
invert_port(0x20, 0, 0xFF);
invert_port(0x20, 1, 0xFF);
// Set the interrupt polarity to be active high and mirroring disabled, so
// pins 1 to 8 trigger INT A and pins 9 to 16 trigger INT B
set_interrupt_polarity(0x20, 1);
mirror_interrupts(0x20, 0);
// Set the interrupts default value to 0x00 so the interrupt will trigger when any pin registers as true
set_interrupt_defaults(0x20, 0, 0x00);
set_interrupt_defaults(0x20, 1, 0x00);
// Set the interrupt type to be 1 for ports A and B so an interrupt is
// fired when the pin does not match the default value
set_interrupt_type(0x20, 0, 0xFF);
set_interrupt_type(0x20, 1, 0xFF);
// Enable interrupts for all pins
set_interrupt_on_port(0x20, 0, 0xFF);
set_interrupt_on_port(0x20, 1, 0xFF);
while (1){
// read the interrupt status for each port.
// If the status is not 0 then an interrupt has occured on one of the pins
// so read the value from the interrupt capture.
if (read_interrupt_status(0x20, 0) != 0){
printf("Port 0: %x \n", read_interrupt_capture(0x20,0));
}
if (read_interrupt_status(0x20, 1) != 0){
printf("Port 1: %x \n", read_interrupt_capture(0x20,1));
}
usleep(200000); // sleep 0.2 seconds
}
return (0);
}
The difference between this and your code is I changed the interrupt type to be 1 on each pin so it will fire when the pin does not match the default value and I changed the while loop so on each loop the interrupt status for each port is checked and it only prints the result if the interrupt has fired.
I used the read_interrupt_capture() function to get the value of the interrupt when it fired and print that to the display.
When the code runs it will print the status repeatedly when a pin is connected to ground. If you only want it to print when the pin state changes change the set_interrupt_type(0x20, 0, 0xFF); to set_interrupt_type(0x20, 0, 0x00);
I have uploaded a copy of the c code to our GitHub repository at demo-iopiinterrupt.c
27/03/2020
Posted by:
Robspalu
Thanks for the new demo, just what I needed to help me understand my problem.
I have change the interrupt type so I detect each state change.
My intention now is to create a C library ABE_IoPi and a corresponding Lazarus wrapper so I can access the IoPi board from a Lazarus application I have already written, if successful I will need some more IoPi boards.
Thanks again for your help
Dave.
Forum Notice – Closure to New Posts
As part of our compliance with the UK’s Online Safety Act, the AB Electronics UK support forum is now closed to new posts and replies.
We understand the importance of continued support for our products, so if you have a technical query or require assistance, please use the Contact Form or consult our Knowledge Base for helpful articles and documentation.
We appreciate your understanding and continued support.
Note: documents in Portable Document Format (PDF) require Adobe Acrobat Reader 5.0 or higher to view.
Download Adobe Acrobat Reader or other PDF reading software for your computer or mobile device.