Note: 15th August 2019: This blog post is old and isn't worth reading (apart from the comments and for historical reasons), because there is a newer blog post here:
BeagleBone Black (BBB) and PocketBeagle I/O (GPIO), SPI and I2C Library for C – 2019 Edition
(Note: The BBB supports all programming languages - this post is for those who wish/need to use C, but it's not always an ideal language - it is strongly recommended to investigate the in-built, web-browser based 'Cloud9' developement environment and Bonescript).
Note 2: The library is well worth considering for C code projects, because it is very easy to use. The text below describes it in detail, but to summarise: All that is needed is to include the header file, and then do iolib_init(), and then set directions for ports using iolib_setdir specifying the physical header and pin number on the BBB, and then using pin_high() or pin_low() functions to set pins high or low, and using is_high() and is_low() to check the levels for input pins. Call iolib_free() at the end of your code.
Note 3: vegetableavenger has taken the original code and extended it to a more complete library, and also created some very good demos to do things like control 7-segment LED displays and ultrasonic range sensors. After you have read this post and comments to get an understanding how to use the library, it is suggested to go to Meng-Lun's resource here to download the code and any demos that you are interested in. All are documented with graphic diagrams.
Introduction
There are Python I/O libraries for the BBB, however I had not seen a C library – I may have missed it. Not everyone uses Python! And I’ve been mainly using the PRU. So, I spent a few hours creating a basic library.
It allows you to program in C and control simple I/O, up to around 2MHz speed. (This is quite slow I/O, but it is very simple to use because it hides all the detail. If you need extremely high speed I/O, the BBB can operate I/O pins to 200MHz using the in-built dual PRU processors by the way).
The main benefit of this library is that it is very easy to use, and the 2MHz speed can be acceptable for many use-cases.
Here is how to use it:
- Type make clean followed by make all to build the library
- Copy the libiofunc.a into /usr/lib
- Copy the iolib.h into /usr/include
- Write your C program, as shown in the example below; it will use functions iolib_init(), iolib_setdir(), pin_high(), pin_low(), is_high(), is_low() and iolib_free()
- Compile using: gcc -c main.c -o main.o followed by gcc main.o –liofunc –o main_app
- Execute your program as usual using ./main_app
Here are some snippets of an example C program. A full example is in the attached zip file.
(Note: the zip file is left below and will eventually be removed, however vegetableavenger now has a repository for the latest code at this location).
First, in the C file, include iolib.h:
#include <iolib.h>
In the main() function, initialise the library:
iolib_init();
Then, tell the library which pins you want as inputs or outputs. Here, header P8 pin 12 is set as an output:
iolib_setdir(8, 12, DIR_OUT);
Set the pin high or low using the pin_high or pin_low functions:
pin_high(8,12); pin_low(8,12);
If you need a short delay (0-999 milliseconds), use this function shown here. For longer delays, use sleep():
iolib_sleep_ms(100);
For inputs, you can check if a pin is high or low using is_high or is_low functions. This example checks header P8 pin 11 (assuming it was set as an input):
if (is_high(8,11)) printf(“high”);
At the end of the program:
iolib_free();
It is not a sophisticated library (it does not perform' pinmux' which is used to manage the vast multi-function capabilities of each pin through mode changes) but it should be good enough for simple control of hardware. With the appropriate circuitry it is fine for controlling relays, LEDs and handling switch inputs. The absense of this mode changing capability means that not all pins will work, so please test the pin before you use it (some example code supplied that will let you choose any pin and the direction (input or output), and then it will toggle it so that you can test it with an LED, and will print the state so you can test it as an input using a switch). When I get a chance, I will test each pin to confirm if the default state is in the correct mode for GPIO or not and write a list. But for now, please test the pin you wish to use (and use the comments section to help others by reporting which pins are suitable without requiring any pinmux performed).
Example circuit and code to demonstrate the functions
The example code can be compiled using:
gcc test_app.c –liofunc –o test_app
When run, it will blink an LED at a slow or fast rate. The rate depends on a switch input being pressed or not.
Here is the circuit layout. The BBB offers 0V and 3.3V pins on the header, and these were used to connect the LED and switch:
The code is quite short and easy to follow:
#include <stdio.h> #include <stdlib.h> #include "iolib.h" int main(void) { int del; iolib_init(); iolib_setdir(8,11, DIR_IN); iolib_setdir(8,12, DIR_OUT); while(1) { if (is_high(8,11)) { del=100; // fast speed } if (is_low(8,11)) { del=500; // slow speed } pin_high(8,12); iolib_delay_ms(del); pin_low(8,12); iolib_delay_ms(del); } iolib_free(); return(0); }
Here is what the circuit looks like:
The source code is supplied if you wish to make changes (there may be bugs, so please check each pin with an LED or a switch before you use it, and let me know of any errors).
Note that the library will try to return an error code if it believes an incorrect pin is being used (not all pins are available).
So, you can do:
If (iolib_setdir(8,11, DIR_IN) != 0) printf(“Error!\n”);
To test a pin, compile up the attached program file testio.c and run it. It will prompt you for the desired pin to test, and will then perform the LED toggling or text output indication of high/low for the pin as mentioned earlier.
The graphic template is attached for documenting any projects.
vegetableavenger also has another example that implements a digital temperature sensor at this location where the latest copy of the library can be downloaded. See the Demo_ADT7301 folder there. See the Demo_LED folder for the example illustrated above.
A few pins confirmed to be in GPIO mode by default without requiring any mode changes. I have not tried many pins.
Header P8:
Pins 11, 12, 15, 16
Edit: nikorun2 has tested further pins on P8, see comments below:
Header P8:
Pins 3, 4, 5, 6, 11, 12, 15, 16, 20, 21, 22, 23, 24, 25, 26
Top Comments