Support Forum

Share your projects and post your questions

Register   or   Sign In
The Forum

Interrupts in C

1239 Views - Created 27/03/2020

27/03/2020

Posted by:
Robspalu

Robspalu Avatar

Hi,

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

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

Hello Dave

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

Robspalu Avatar

Hi Andrew,

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

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

Hi Dave

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 https://github.com/abelectronicsuk/ABElectronics_C_Libraries/blob/master/IOPi/demos/demo-iopiinterrupt.c

27/03/2020

Posted by:
Robspalu

Robspalu Avatar

Hi Andrew,

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.

Sign in to post your reply

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.