About Us Knowledge Base Community Forum Electronics Toolbox FAQ Shipping & Delivery

Community Forum

Share your projects and post your questions

Search
Register or Sign In
Forum

Interrupts in C

322 Views - Created 27/03/2020

27/03/2020

Posted by:
Robspalu

Users 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

Users Avatar

Location:
United Kingdom

Users Twitter  Users 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 be 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

 

AB Electronics UK Tech Support

27/03/2020

Posted by:
Robspalu

Users 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

Users Avatar

Location:
United Kingdom

Users Twitter  Users 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 <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

#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/demo-iopiinterrupt.c

AB Electronics UK Tech Support

27/03/2020

Posted by:
Robspalu

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

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.