PcDuino GPIO access from C

From Hamsterworks Wiki!

Jump to: navigation, search

This pcDuino project was completed March 2013.

The very first thing you might want to do is flash a LED and read the value of a switch. You will find out how to physically connect the switch or LED (and a current limiting resistor) to a pin elsewhere on the web, and if you want you can use the Arduino-like interface library provided with the pcDuino. However, here is how to do it access the port using Linux's native 'sysfs' interface.

Writing to a GPIO pin

The first thing is to write either '1' into the "gpio" file in the "/sys/devices/virtual/misc/gpio/mode" directory to set the GPIO pin as an output pin. The write the desired value into the "gpio" file in "/sys/devices/virtual/misc/gpio/pin" to set the pin's value. If using the stdio functions you will need to call "fflush()" with the file handle to ensure that data is not it held in the file handle's buffer.

/************************************************************
* gpiotest.c : Accessing the GPIO directly from C
*
* Author : Mike Field <hamster@snap.net.nz>
*
* Turns the desired GPIO pin on and off ten times
*
* Supplied as is, where is, I don't care what you do with it!
*************************************************************/

#include <stdio.h>
#include <stdlib.h>

#define MODE_FILE_FORMAT "/sys/devices/virtual/misc/gpio/mode/gpio%d"
#define PIN_FILE_FORMAT  "/sys/devices/virtual/misc/gpio/pin/gpio%d"

int main(int c, char *v[])
{
  char buffer[128];
  FILE *modefile, *pinfile;
  int pin,i;

  if(c != 2) {
    fprintf(stderr,"usage: %s [pin]\n",v[0]);
    exit(2);
  }
  pin = atoi(v[1]);

  /* Open the GPIO control files */
  sprintf(buffer,MODE_FILE_FORMAT,pin);
  modefile = fopen(buffer,"w");
  if(modefile == NULL)
  {
    fprintf(stderr,"Unable to open mode file: %s\n",buffer);
    exit(2);
  }

  sprintf(buffer,PIN_FILE_FORMAT,pin);
  pinfile = fopen(buffer,"w");
  if(pinfile == NULL)
  {
    fprintf(stderr,"Unable to open pin file: %s\n",buffer);
    exit(2);
  }

  /* Set the pin to be an output pin */
  fwrite("1",1,1,modefile);

  /* Turn the pin off or on */
  for(i = 0; i < 10; i++)
  {
    fwrite("1",1,1,pinfile);
    fflush(pinfile);
    sleep(1);
    fwrite("0",1,1,pinfile);
    fflush(pinfile);
    sleep(1);
  }

  fclose(modefile);
  fclose(pinfile);
  return 0;
}

If you are worried about glitches on the output you might want to write the desired value to the 'pin' file before you set the pin's mode.

Reading the value of a GPIO pin

To get the value of the pin just read the value from the 'pin' file, after writing '0' to the 'mode' file. It is a bit more complex than writing, as you have to read all the data from the 'pin' file (i.e. till EOF is reached) before the kernel presents a new value - If you call fseek() before EOF is reached your input will never change! The code cheats a little and attempts to read four characters every time.

/************************************************************
* input.c : Read directly from the GPIO directly from C
*
* Author : Mike Field <hamster@snap.net.nz>
*
* Prints out the value presented on the GPIO port
*
* Supplied as is, where is, I don't care what you do with it!
*************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define MODE_FILE_FORMAT "/sys/devices/virtual/misc/gpio/mode/gpio%d"
#define PIN_FILE_FORMAT  "/sys/devices/virtual/misc/gpio/pin/gpio%d"

int main(int c, char *v[])
{
  char buffer[128];
  FILE *modefile, *pinfile;
  int pin;

  if(c != 2) {
    fprintf(stderr,"usage: %s [pin]\n",v[0]);
    exit(2);
  }
  pin = atoi(v[1]);

  /* Open the GPIO control files */
  sprintf(buffer,MODE_FILE_FORMAT,pin);
  modefile = fopen(buffer,"w");
  if(modefile == NULL)
  {
    fprintf(stderr,"Unable to open mode file: %s\n",buffer);
    exit(2);
  }

  sprintf(buffer,PIN_FILE_FORMAT,pin);
  pinfile = fopen(buffer,"r");
  if(pinfile == NULL)
  {
    fprintf(stderr,"Unable to open pin file: %s\n",buffer);
    exit(2);
  }

  /* Set the pin to be an input pin */
  fwrite("0",1,1,modefile);

  /* Read and display the value of the GPIO pin */
  while(1)
  {
    char buffer[4];
    fseek(pinfile, 0, SEEK_SET);
    if(fread(buffer,1,4,pinfile) <= 0) {
      fprintf(stderr,"Error on read\n");
      break;
    }
    putchar(buffer[0]);
    fflush(stdout);
    sleep(1);
  }

  fclose(modefile);
  fclose(pinfile);
  return 0;
}

Personal tools