An interrupt is a signal to the computer to stop what it is doing and do something else. These are used extensively by the operating system, but an application can use them as well. If you have a GPIO input that needs to be responded to, you could poll the GPIO pin in a loop waiting for it to change, but this can be unreliable for very brief state changes. It is also wasteful of the CPU. The better way is to assign an interrupt that will be activated when the GPIO pin changes state.
I code all my projects in C and use Gordon's WiringPi API. This library makes it much easier to use GPIO. Interrupts are now supported using the wiringPiISR function. (The waitForInterrupt function is deprecated and should not be used.) Using interrupts takes only three steps:
- Create a function to be called when the GPIO pin changes state. This must be defined like this: void myInterrupt(void)
- Initialize the WiringPi library by calling wiringPiSetup
- Call wiringPiISR to configure the interrupt
You can choose to have your interrupt called when the pin goes low, goes high, or both (INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH)
My interrupts simply increment a global variable. The value of this variable is then checked periodically (typically once per second) and the count is converted into the appropriate units for the device.
An example of how to use an interrupt is shown below.
#include <stdio.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <wiringPi.h> // Use GPIO Pin 17, which is Pin 0 for wiringPi library #define BUTTON_PIN 0 // the event counter volatile int eventCounter = 0; // ------------------------------------------------------------------------- void myInterrupt(void) { eventCounter++; } // ------------------------------------------------------------------------- int main(void) { // sets up the wiringPi library if (wiringPiSetup () < 0) { fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno)); return 1; } // set Pin 17/0 generate an interrupt on high-to-low transitions // and attach myInterrupt() to the interrupt if ( wiringPiISR (BUTTON_PIN, INT_EDGE_FALLING, &myInterrupt) < 0 ) { fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)); return 1; } // display counter value every second. while ( 1 ) { printf( "%d\n", eventCounter ); eventCounter = 0; delay( 1000 ); // wait 1 second } return 0; }
All of the code from my weather station can be found at
https://github.com/tedhale/raspberry-pi-hobbyist
You can also get it using git:
git clone https://github.com/tedhale/raspberry-pi-hobbyist.git
Professor D. Thiebaut wrote this code in 2013
ReplyDeletehttp://cs.smith.edu/dftwiki/index.php/Tutorial:_Interrupt-Driven_Event-Counter_on_the_Raspberry_Pi
Not only is the code stolen, it's also incorrect. volatile is NOT a synchronization primitive across threads.
ReplyDeleteNever said the code was mine, just put it out there as an example.
ReplyDeleteCorrect, "volatile" is not a synchronization primitive. It is a flag to the compiler that the variable may change out of scope and no cached version should be used.
Be a good troll and explain to me how it is incorrect.
Hello! your project looks very nice. I have some similar and wold ask how it would be possible implementing input threads ie display, buttons ?
ReplyDelete