diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 7052a93..83f6f82 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -283,7 +283,7 @@ if (value==HIGH) ## Interrupts -### wiringPiISR (klassische Version) +### wiringPiISR Registriert eine Interrupt Service Routine (ISR) bzw. Funktion die bei Flankenwechsel ausgeführt wird. Es werden bei dieser klassischen Version keine Parameter and die ISR übergeben. @@ -304,6 +304,7 @@ int wiringPiISR(int pin, int mode, void (*function)(void)); > 0 ... Erfolgreich +Beispiel siehe [wiringPiISRStop](#wiringPiISRStop). ### wiringPiISR2 @@ -317,28 +318,30 @@ int wiringPiISR2(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfi ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). -``edgeMode``: Auslösende Flankenmodus +``edgeMode``: Auslösender Flankenmodus + - INT_EDGE_RISING ... Steigende Flanke - INT_EDGE_FALLING ... Fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke ``*function``: Funktionspointer für ISR mit Parameter struct WPIWfiStatus und einem Pointer: -```C +```C struct WPIWfiStatus { int statusOK; // -1: error (return of 'poll' command), 0: timeout, 1: irq processed, next data values are valid if needed unsigned int pinBCM; // gpio as BCM pin int edge; // INT_EDGE_FALLING or INT_EDGE_RISING long long int timeStamp_us; // time stamp in microseconds }; -``` +``` -``debounce_period_us``: Entprellzeit in Microsekunden, 0 ms schaltet das Entprellen ab +``debounce_period_us``: Entprellzeit in Microsekunden, 0 schaltet das Entprellen ab ``userdata``: Pointer der beim Aufruf der ISR übergeben wird ``Rückgabewert``: > 0 ... Erfolgreich + Beispiel siehe [waitForInterrupt2](#waitForInterrupt2). ### wiringPiISRStop @@ -346,15 +349,40 @@ Deregistriert die Interrupt Service Routine (ISR) auf einem Pin. >>> ```C -int wiringPiISRStop (int pin) +int wiringPiISRStop (int pin); ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). ``Rückgabewert``: + > 0 ... Erfolgreich +**Beispiel:** + +>>> +```C +static volatile int edgeCounter; + +static void isr(void) { + edgeCounter++; +} + +int main (void) { + wiringPiSetupPinType(WPI_PIN_BCM); + edgeCounter = 0; + + wiringPiISR(17, INT_EDGE_RISING, &isr); + + Sleep(1000); + printf("%d rising edges\n", edgeCounter); + + wiringPiISRStop(17); +} +``` + + ### waitForInterrupt Funktion ist nicht mehr verfügbar, es wird nur noch die ``waitForInterrupt2`` unterstützt! @@ -372,21 +400,21 @@ struct WPIWfiStatus wfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, u ``` ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). +``edgeMode``: Auslösender Flankenmodus -``edgeMode``: Auslösende Flankenmodus - INT_EDGE_RISING ... Steigende Flanke - INT_EDGE_FALLING ... Fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke -``mS``: Timeout in Milisekunden. - - \-1 warten ohne timeout - - 0 wartet nicht - - 1...n wartet maximal n Millisekunden +``ms``: Timeout in Milisekunden. + - \-1 ... Warten ohne Timeout + - 0 ... Wartet nicht + - 1...n ... Wartet maximal n Millisekunden ``debounce_period_us``: Entprellzeit in Microsekunden, 0 schaltet Entprellen ab. -``Rückgabewert``: -```C +``Rückgabewert``: +```C struct WPIWfiStatus { int statusOK; // -1: error (return of 'poll' command), 0: timeout, 1: irq processed, next data values are valid if needed unsigned int pinBCM; // gpio as BCM pin @@ -395,8 +423,9 @@ struct WPIWfiStatus { }; ``` -### Beispiel -```C +**Beispiel:** + +```C /* * isr_debounce.c: * Wait for Interrupt test program WiringPi >=3.16 - ISR2 method @@ -421,21 +450,21 @@ struct WPIWfiStatus { // OUTpin : connected to a LED with 470 Ohm resistor in series to GND. Toggles LED with every push button pressed. //************************************* #define IRQpin 16 -#define OUTpin 12 +#define OUTpin 12 int toggle = 0; -static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) { +static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) { // struct timeval now; long long int timenow, diff; struct timespec curr; char *edgeType; - + if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) { printf("clock_gettime error"); return; } - + timenow = curr.tv_sec * 1000000LL + curr.tv_nsec/1000L; // convert to microseconds diff = timenow - wfiStatus.timeStamp_us; if (wfiStatus.edge == INT_EDGE_RISING) @@ -446,11 +475,11 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) { edgeType = "none"; printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.gpioPin, edgeType, wfiStatus.timeStamp_us, timenow, diff); if (toggle == 0) { - digitalWrite (OUTpin, HIGH) ; + digitalWrite (OUTpin, HIGH); toggle = 1; } else { - digitalWrite (OUTpin, LOW) ; + digitalWrite (OUTpin, LOW); toggle = 0; } } @@ -459,55 +488,50 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) { int main (void) { int major, minor; - wiringPiVersion(&major, &minor); - printf("\nISR debounce test (WiringPi %d.%d)\n\n", major, minor); - - wiringPiSetupGpio() ; + wiringPiSetupGpio(); pinMode(IRQpin, INPUT); - // pull up/down mode (PUD_OFF, PUD_UP, PUD_DOWN) => down pullUpDnControl(IRQpin, PUD_UP); - pinMode(OUTpin, OUTPUT); digitalWrite (OUTpin, LOW) ; - printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); + printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI); if (wfiStatus.status < 0) { printf("waitForInterrupt returned error\n"); pinMode(OUTpin, INPUT); - return 0; + return 0; } else if (wfiStatus.status == 0) { printf("waitForInterrupt timed out\n\n"); - } + } else { if (wfiStatus.edge == INT_EDGE_FALLING) - printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); + printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); else - printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); + printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); } printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin); printf("To stop program hit return key\n\n"); - - wiringPiISR2(IRQpin, INT_EDGE_BOTH, &wfi, BOUNCETIME, NULL) ; - + + wiringPiISR2(IRQpin, INT_EDGE_BOTH, &wfi, BOUNCETIME, NULL); + getc(stdin); - - wiringPiISRStop (IRQpin) ; + + wiringPiISRStop (IRQpin); pinMode(OUTpin, INPUT); - return 0 ; + return 0; } ``` -Augabe am Terminal: +Ausgabe am Terminal: -``` +``` pi@RaspberryPi:~/wiringpi-test-v3.16 $ gcc -o isr_debounce isr_debounce.c -l wiringPi pi@RaspberryPi:~/wiringpi-test-v3.16 $ ./isr_debounce @@ -533,7 +557,7 @@ gpio BCM = 16, IRQ edge = falling, timestamp = 256543320012 microseconds, timeno gpio BCM = 16, IRQ edge = rising, timestamp = 256544092021 microseconds, timenow = 256544092029, diff = 8 ^C pi@RaspberryPi:~/wiringpi-test-v3.16 $ -``` +``` ## Hardware PWM (Pulsweitenmodulation) diff --git a/documentation/english/functions.md b/documentation/english/functions.md index aad803d..3c54530 100644 --- a/documentation/english/functions.md +++ b/documentation/english/functions.md @@ -120,11 +120,10 @@ Outdated functions (no longer use): **Since Version 3.4:** -``wiringPiSetupPinType`` decides whether WiringPi, BCM or physical PIN numbering is now used, based on the parameter pinType. So it combines the first 3 setup functions together. -``wiringPiSetupGpioDevice`` is the successor to the ``wiringPiSetupSys`` function and now uses "GPIO Character Device Userspace API" in version 1 (from kernel 5.10). More information can be found at [docs.kernel.org/driver-api/gpio/driver.html](https://docs.kernel.org/driver-api/gpio/driver.html) on the parameter pintype, it is again decided which pin numbering is used. +``wiringPiSetupPinType`` decides whether WiringPi, BCM or physical pin numbering is used, based on the parameter pinType. So it combines the first 3 setup functions together. +``wiringPiSetupGpioDevice`` is the successor to the ``wiringPiSetupSys`` function and now uses "GPIO Character Device Userspace API" in version 2 (WiringPi version 3.16 or higher). More information can be found at [docs.kernel.org/driver-api/gpio/driver.html](https://docs.kernel.org/driver-api/gpio/driver.html) on the parameter pintype, it is again decided which pin numbering is used. In this variant, there is no direct access to the GPIO memory (DMA) but rather through a kernel interface that is available with user permissions. The disadvantage is the limited functionality and low performance. - ### wiringPiSetup V2 (outdated) @@ -294,14 +293,15 @@ if (value == HIGH) ### wiringPiISR -Registers an Interrupt Service Routine (ISR) / function that is executed on edge detection. +Registers an Interrupt Service Routine (ISR) / function that is executed on edge detection. +In this classic version, no parameters are passed to the ISR. ```C int wiringPiISR(int pin, int mode, void (*function)(void)); ``` -``pin``: The desired Pin (BCM-, WiringPi-, or Pin-number). -``mode``: Triggering edge mode... +``pin``: The desired pin (BCM-, WiringPi-, or Pin-number). +``mode``: Triggering edge mode - `INT_EDGE_RISING` ... Rising edge - `INT_EDGE_FALLING` ... Falling edge @@ -311,14 +311,50 @@ int wiringPiISR(int pin, int mode, void (*function)(void)); ``Return Value``: > 0 ... Successful - -For example see **[wiringPiISRStop](#wiringpiisrstop)**. +For example see [wiringPiISRStop](#wiringPiISRStop). + + +### wiringPiISR2 + +Registers an Interrupt Service Routine (ISR) / function that is executed on edge detection. +Extended parameters are passed to the ISR. + +>>> +```C +int wiringPiISR2(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus, void* userdata), unsigned long debounce_period_us, void* userdata); +``` + +``pin``: The desired pin (BCM-, WiringPi-, or Pin-number). +``edgeMode``: Triggering edge mode + +- `INT_EDGE_RISING` ... Rising edge +- `INT_EDGE_FALLING` ... Falling edge +- `INT_EDGE_BOTH` ... Rising and falling edge + +``*function``: Function pointer for ISR with the parameter struct WPIWfiStatus and a pointer. +```C +struct WPIWfiStatus { + int statusOK; // -1: error (return of 'poll' command), 0: timeout, 1: irq processed, next data values are valid if needed + unsigned int pinBCM; // gpio as BCM pin + int edge; // INT_EDGE_FALLING or INT_EDGE_RISING + long long int timeStamp_us; // time stamp in microseconds +}; +``` + +``debounce_period_us``: Debounce time in microseconds, 0 disables debouncing. +``userdata``: Pointer that is passed when calling the ISR. + +``Return Value``: + > 0 ... Successful + + For example see [waitForInterrupt2](#waitForInterrupt2). + ### wiringPiISRStop -Deregisters the Interrupt Service Routine (ISR) on a Pin. +Deregisters the Interrupt Service Routine (ISR) on a pin. ```C int wiringPiISRStop (int pin); @@ -344,7 +380,7 @@ int main (void) { wiringPiSetupPinType(WPI_PIN_BCM); edgeCounter = 0; - wiringPiISR (17, INT_EDGE_RISING, &isr); + wiringPiISR(17, INT_EDGE_RISING, &isr); Sleep(1000); printf("%d rising edges\n", edgeCounter); @@ -355,18 +391,171 @@ int main (void) { ### waitForInterrupt -Waits for a previously defined interrupt ([wiringPiISR](#wiringpiisr)) on the GPIO pin. This function should not be used. +The function is no longer available, only ``waitForInterrupt2``! + + +### waitForInterrupt2 + +Waits for a call to the Interrupt Service Routine (ISR) with a timeout and debounce time in microseconds. Blocks the program until the triggering edge occurs or the timeout expires. ```C -int waitForInterrupt (int pin, int mS); +struct WPIWfiStatus wfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned long debounce_period_us) ``` ``pin``: The desired Pin (BCM-, WiringPi-, or Pin-number). -``mS``: Timeout in milliseconds. -``Return Value``: Error -> 0 ... Successful -> -1 ... GPIO Device Chip not successfully opened -> -2 ... ISR was not registered (WiringPiISR must be called) +``ms``: Timeout in milliseconds. + - \-1 ... Wait without timeout + - 0 ... No wait + - 1...n ... Waits for a maximum of n milliseconds + +``debounce_period_us``: Debounce time in microseconds, 0 disables debouncing. + +``Return Value``: +```C +struct WPIWfiStatus { + int statusOK; // -1: error (return of 'poll' command), 0: timeout, 1: irq processed, next data values are valid if needed + unsigned int pinBCM; // gpio as BCM pin + int edge; // INT_EDGE_FALLING or INT_EDGE_RISING + long long int timeStamp_us; // time stamp in microseconds +}; +``` + +**Example:** + +```C +/* + * isr_debounce.c: + * Wait for Interrupt test program WiringPi >=3.16 - ISR2 method + * + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BOUNCETIME 3000 // microseconds +#define BOUNCETIME_WFI 300 +#define TIMEOUT 10000 +//************************************* +// BCM pins +// IRQpin : setup as input with internal pullup. Connected with push button to GND with 1K resistor in series. +// OUTpin : connected to a LED with 470 Ohm resistor in series to GND. Toggles LED with every push button pressed. +//************************************* +#define IRQpin 16 +#define OUTpin 12 + +int toggle = 0; + +static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) { +// struct timeval now; + long long int timenow, diff; + struct timespec curr; + char *edgeType; + + if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) { + printf("clock_gettime error"); + return; + } + + timenow = curr.tv_sec * 1000000LL + curr.tv_nsec/1000L; // convert to microseconds + diff = timenow - wfiStatus.timeStamp_us; + if (wfiStatus.edge == INT_EDGE_RISING) + edgeType = "rising"; + else if (wfiStatus.edge == INT_EDGE_FALLING) + edgeType = "falling"; + else + edgeType = "none"; + printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.gpioPin, edgeType, wfiStatus.timeStamp_us, timenow, diff); + if (toggle == 0) { + digitalWrite (OUTpin, HIGH); + toggle = 1; + } + else { + digitalWrite (OUTpin, LOW); + toggle = 0; + } +} + + +int main (void) +{ + int major, minor; + wiringPiVersion(&major, &minor); + printf("\nISR debounce test (WiringPi %d.%d)\n\n", major, minor); + + wiringPiSetupGpio(); + pinMode(IRQpin, INPUT); + // pull up/down mode (PUD_OFF, PUD_UP, PUD_DOWN) => down + pullUpDnControl(IRQpin, PUD_UP); + pinMode(OUTpin, OUTPUT); + digitalWrite (OUTpin, LOW) ; + + printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); + struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI); + if (wfiStatus.status < 0) { + printf("waitForInterrupt returned error\n"); + pinMode(OUTpin, INPUT); + return 0; + } + else if (wfiStatus.status == 0) { + printf("waitForInterrupt timed out\n\n"); + } + else { + if (wfiStatus.edge == INT_EDGE_FALLING) + printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); + else + printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); + } + + printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin); + printf("To stop program hit return key\n\n"); + + wiringPiISR2(IRQpin, INT_EDGE_BOTH, &wfi, BOUNCETIME, NULL); + + getc(stdin); + + wiringPiISRStop (IRQpin); + pinMode(OUTpin, INPUT); + + return 0; +} +``` + +Output on terminal: + +``` +pi@RaspberryPi:~/wiringpi-test-v3.16 $ gcc -o isr_debounce isr_debounce.c -l wiringPi +pi@RaspberryPi:~/wiringpi-test-v3.16 $ ./isr_debounce + +ISR debounce test (WiringPi 3.16) + +Testing waitForInterrupt on both edges IRQ @ GPIO16, timeout is 10000 +waitForInterrupt: GPIO pin 16 falling edge fired at 256522528012 microseconds + +Testing IRQ @ GPIO16 on both edges and bouncetime 3000 microseconds. Toggle LED @ GPIO12 on IRQ. + +To stop program hit return key + +gpio BCM = 16, IRQ edge = rising, timestamp = 256522668010 microseconds, timenow = 256522668017, diff = 7 +gpio BCM = 16, IRQ edge = falling, timestamp = 256536364014 microseconds, timenow = 256536364021, diff = 7 +gpio BCM = 16, IRQ edge = rising, timestamp = 256536952011 microseconds, timenow = 256536952018, diff = 7 +gpio BCM = 16, IRQ edge = falling, timestamp = 256537856010 microseconds, timenow = 256537856016, diff = 6 +gpio BCM = 16, IRQ edge = rising, timestamp = 256538744011 microseconds, timenow = 256538744018, diff = 7 +gpio BCM = 16, IRQ edge = falling, timestamp = 256539664010 microseconds, timenow = 256539664017, diff = 7 +gpio BCM = 16, IRQ edge = rising, timestamp = 256540516010 microseconds, timenow = 256540516016, diff = 6 +gpio BCM = 16, IRQ edge = falling, timestamp = 256541560013 microseconds, timenow = 256541560022, diff = 9 +gpio BCM = 16, IRQ edge = rising, timestamp = 256542360010 microseconds, timenow = 256542360016, diff = 6 +gpio BCM = 16, IRQ edge = falling, timestamp = 256543320012 microseconds, timenow = 256543320020, diff = 8 +gpio BCM = 16, IRQ edge = rising, timestamp = 256544092021 microseconds, timenow = 256544092029, diff = 8 +^C +pi@RaspberryPi:~/wiringpi-test-v3.16 $ +``` + ## Hardware Pulse Width Modulation (PWM)