├── GPIO ├── README.md └── gpio_ctrl.c ├── I2C ├── README.md └── mcp23017.c ├── LICENSE ├── Makefile ├── README.md ├── SPI ├── README.md └── mcp23s08.c └── UART ├── README.md └── uart_test.c /GPIO/README.md: -------------------------------------------------------------------------------- 1 | # GPIO Example 2 | 3 | For this example I use a LED and a push button. 4 | 5 | The LED is connected to GPIO 16 and the button to GPIO 16 of a Raspberry Pi 3. Here is a link to the [RPi's pinout](https://pinout.xyz/#). 6 | -------------------------------------------------------------------------------- /GPIO/gpio_ctrl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | int fd; 12 | struct gpiohandle_request led, button; 13 | struct gpiohandle_data data; 14 | 15 | /* Open the gpiochip device file */ 16 | fd = open("/dev/gpiochip0", O_RDWR); 17 | if(fd < 0) { 18 | perror("Error opening gpiochip0"); 19 | return -1; 20 | } 21 | 22 | /* Setup LED to output */ 23 | led.flags = GPIOHANDLE_REQUEST_OUTPUT; 24 | strcpy(led.consumer_label, "LED"); 25 | memset(led.default_values, 0, sizeof(led.default_values)); 26 | led.lines = 1; 27 | led.lineoffsets[0] = 16; 28 | 29 | if(ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &led) < 0) { 30 | perror("Error setting GPIO 16 to output"); 31 | close(fd); 32 | return -1; 33 | } 34 | /* Setup button to input */ 35 | button.flags = GPIOHANDLE_REQUEST_INPUT; 36 | strcpy(button.consumer_label, "LED"); 37 | memset(button.default_values, 0, sizeof(button.default_values)); 38 | button.lines = 1; 39 | button.lineoffsets[0] = 20; 40 | 41 | if(ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &button) < 0) { 42 | perror("Error setting GPIO 20 to input"); 43 | close(led.fd); 44 | close(fd); 45 | return -1; 46 | } 47 | 48 | /* Let's set the LED */ 49 | data.values[0] = 1; 50 | if(ioctl(led.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data) < 0) 51 | perror("Error setting GPIO to 1"); 52 | 53 | /* Reading button's state */ 54 | if(ioctl(button.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data) < 0) 55 | perror("Error setting GPIO to 1"); 56 | 57 | printf("Button is %s\n", (data.values[0] > 0) ? "pressed" : "not pressed"); 58 | 59 | sleep(2); 60 | 61 | close(fd); 62 | close(led.fd); 63 | close(button.fd); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /I2C/README.md: -------------------------------------------------------------------------------- 1 | # I2C Example 2 | 3 | For this example I use a MCP23017 GPIO Expander as an I2C Device and a Raspberry Pi as the I2C Controller. 4 | 5 | GPIOA0 is connected to a LED, GPIOA1 to a button. 6 | 7 | Here is a link to the [datasheet of the MCP23017](http://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf) 8 | -------------------------------------------------------------------------------- /I2C/mcp23017.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char *argv[]) { 10 | int i2c_bus; 11 | uint8_t data[2]; 12 | 13 | /* Let's open the bus */ 14 | i2c_bus = open("/dev/i2c-1", O_RDWR); 15 | if(i2c_bus < 0) { 16 | perror("Error opening I2C Bus"); 17 | return -1; 18 | } 19 | 20 | /* Set the slave address */ 21 | if(ioctl(i2c_bus, I2C_SLAVE, 0x20) < 0) { 22 | perror("Error setting slave address"); 23 | close(i2c_bus); 24 | return -1; 25 | } 26 | 27 | /* Now let's access the bus */ 28 | /* Set the GPIOA's direction */ 29 | data[0] = 0x0; 30 | data[1] = 0xfe; 31 | 32 | if(write(i2c_bus, data, sizeof(data)) != 2) { 33 | perror("Error writing to I2C bus"); 34 | close(i2c_bus); 35 | return -1; 36 | } 37 | 38 | /* Set the LED's state */ 39 | data[0] = 0x14; 40 | if(argc > 1) 41 | data[1] = atoi(argv[1]) > 0; 42 | else 43 | data[1] = 0x0; 44 | 45 | if(write(i2c_bus, data, sizeof(data)) != 2) { 46 | perror("Error writing to I2C bus"); 47 | close(i2c_bus); 48 | return -1; 49 | } 50 | 51 | /* Let's read the button's state */ 52 | /* Frist write out the address */ 53 | data[0] = 0x12; 54 | if(write(i2c_bus, data, 1) != 1) { 55 | perror("Error writing to I2C bus"); 56 | close(i2c_bus); 57 | return -1; 58 | } 59 | 60 | /* Let's read the value back */ 61 | if(read(i2c_bus, data, 1) != 1) { 62 | perror("Error reading from I2C bus"); 63 | close(i2c_bus); 64 | return -1; 65 | } 66 | 67 | printf("Button is %s\n", (data[0] & (1<<1)) ? "Pressed" : "Not pressed"); 68 | close(i2c_bus); 69 | return 0; 70 | } 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: I2C_example SPI_example GPIO_example 2 | echo "All examples build" 3 | 4 | I2C_example: I2C/mcp23017.c 5 | gcc I2C/mcp23017.c -o I2C/mcp23017 6 | 7 | SPI_example: SPI/mcp23s08.c 8 | gcc SPI/mcp23s08.c -o SPI/mcp23s08 9 | 10 | GPIO_example: GPIO/gpio_ctrl.c 11 | gcc GPIO/gpio_ctrl.c -o GPIO/gpio_ctrl 12 | 13 | clean: 14 | rm GPIO/gpio_ctrl SPI/mcp23s08 I2C/mcp23017 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linux_Embedded_Interfaces 2 | 3 | Minimal Examples for how to use Embedded Interfaces from Linux Userspace 4 | 5 | This repository contains examples for: 6 | 7 | * SPI Interface with MCP23S08 8 | * I2C Interface with MCP23017 9 | * GPIO as Input and Output 10 | * UART with a UART-to-USB adapter 11 | 12 | I use a Raspberry Pi 3 for these examples, but it should also work with other GNU/Linux Embedded Devices (e.g. Beaglebones, ...). 13 | -------------------------------------------------------------------------------- /SPI/README.md: -------------------------------------------------------------------------------- 1 | # SPI Example 2 | 3 | For this example I am using a MCP23S08 GPIO Expander as a SPI slave and a Raspberry Pi as the SPI Master. 4 | 5 | GPIOA0 is connected to a LED, GPIOA1 to a button. 6 | 7 | Here is a link to the [datasheet of the MCP23S08](https://ww1.microchip.com/downloads/en/DeviceDoc/MCP23008-MCP23S08-Data-Sheet-20001919F.pdf) 8 | -------------------------------------------------------------------------------- /SPI/mcp23s08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | uint8_t mode = 0; 11 | uint32_t speed = 500000; 12 | uint8_t bits = 8; 13 | 14 | /** 15 | * @brief function makes a SPI transfer 16 | * 17 | * @param fd File descriptor to SPI bus 18 | * @param data Data array with output (write) data 19 | * will be overwritten with the received input data 20 | * @param length Length of the data array 21 | */ 22 | void spi_transfer(int fd, uint8_t *data, int length) { 23 | struct spi_ioc_transfer spi[length]; 24 | int i; 25 | 26 | /* Setup transfer struct */ 27 | for (i=0; i 1) 85 | data[2] = atoi(argv[1]) > 0; 86 | else 87 | data[2] = 0x0; 88 | spi_transfer(fd, data, 3); 89 | 90 | /* Read Button */ 91 | data[0] = 0x41; 92 | data[1] = 0x9; 93 | data[2] = 0x00; 94 | spi_transfer(fd, data, 3); 95 | 96 | printf("Button is %s\n", ((data[2] & (1<<1)) > 0) ? "pressed" : "not pressed"); 97 | 98 | close(fd); 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /UART/README.md: -------------------------------------------------------------------------------- 1 | Connect the UART Pins of a Raspberry Pi or similar to an UART-to-USB adapter and you should be able to use this example. 2 | -------------------------------------------------------------------------------- /UART/uart_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | int fd, len; 9 | char text[255]; 10 | struct termios options; /* Serial ports setting */ 11 | 12 | fd = open("/dev/serial0", O_RDWR | O_NDELAY | O_NOCTTY); 13 | if (fd < 0) { 14 | perror("Error opening serial port"); 15 | return -1; 16 | } 17 | 18 | /* Read current serial port settings */ 19 | // tcgetattr(fd, &options); 20 | 21 | /* Set up serial port */ 22 | options.c_cflag = B9600 | CS8 | CLOCAL | CREAD; 23 | options.c_iflag = IGNPAR; 24 | options.c_oflag = 0; 25 | options.c_lflag = 0; 26 | 27 | /* Apply the settings */ 28 | tcflush(fd, TCIFLUSH); 29 | tcsetattr(fd, TCSANOW, &options); 30 | 31 | /* Write to serial port */ 32 | strcpy(text, "Hello from my RPi\n\r"); 33 | len = strlen(text); 34 | len = write(fd, text, len); 35 | printf("Wrote %d bytes over UART\n", len); 36 | 37 | printf("You have 5s to send me some input data...\n"); 38 | sleep(5); 39 | 40 | /* Read from serial port */ 41 | memset(text, 0, 255); 42 | len = read(fd, text, 255); 43 | printf("Received %d bytes\n", len); 44 | printf("Received string: %s\n", text); 45 | 46 | 47 | close(fd); 48 | return 0; 49 | } 50 | --------------------------------------------------------------------------------