Outils pour utilisateurs

Outils du site


robotics:computing:linux_asynchronous_serial_programming_how_to

Ceci est une ancienne révision du document !


Introduction

This article describes asynchrous serial programming using signal handler.

References
Hardware used :
Softwares :
  • Ubuntu 10.10 installed on both Roboard and desktop PC : http://www.ubuntu.com/
  • Package build-essential already installed on your Ubuntu operating system.

Asynchronous serial I/O library

The following code is very simple. There is just one function to initialize the serial communication. Only serial port device, baudrate and if there is a parity checking can be set.
Everything else is hard coded, supposing we use 8 bits of data, 1 stop bit and a prefix on parity error.

But the most important thing is the definition of a signal handler function type. All signal handlers return nothing and take one integer in parameter. This integer is the signal which throws the interruption. Here is a light description of how signals work :

  • Data are available on the serial port
  • A signal SIGIO is send to the application waiting for it
  • This application stops its actual work
  • And it calls the signal handler function
  • At the end of the handler, application go back to its previous work.

This signal handler is given as a parameter of the serialConfiguration function. Then you can develop your own handler and just pass it to serialConfiguration.

Here is the header file serialCom.h :

#ifndef _SERIALCOM_H_
#define _SERIALCOM_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include <termios.h>

  /* Controls :  CS8      = 8 bits
   *             CREAD    = Enable reading */
#define SERIAL_CONTROL  (CS8 | CREAD)

  /* Input    :  PARMRK   = If IGNPAR is not set, prefix a character with a parity error  or
   framing  error  with  \377  \0 */
#define SERIAL_INPUT    PARMRK

  /* Handler type definition */
  typedef void
  (*serial_handler)(int status);

  /* Serial port initialization function */
  int
  serialConfiguration(serial_handler, const char* device, tcflag_t baudrate,
      char parity);

#ifdef __cplusplus
}
#endif

#endif

And the source file serialCom.cpp with more explanations in code comments :

#ifdef __cplusplus
extern "C"
{
#endif

#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <termios.h>
#include <serialCom.h>

  int
  serialConfiguration(serial_handler handler, const char *device,
      tcflag_t baudrate, char parity)
  {
    /* Definition of new serial port configuration */
    struct termios newtio;
    /* Definition of signal action */
    struct sigaction saio;

    /* Open the device
     * O_RDWR     : open in read/write mode
     * O_NONBLOCK : open in not blocked mode. Read will return immediatly */
    int fdesc = open(device, O_RDWR | O_NONBLOCK);
    if (fdesc < 0)
      {
        perror(device);
        return fdesc;
      }

    /* Install the signal handler before making the device asynchronous */
    saio.sa_handler = handler;
    saio.sa_flags = 0;
    saio.sa_restorer = NULL;
    sigaction(SIGIO, &saio, NULL);

    /* Allow the process to receive SIGIO */
    fcntl(fdesc, F_SETOWN, getpid());
    /* Make the file descriptor asynchronous.
     * It is not possible to enable SIGIO receiving by specifying
     * O_ASYNC when calling open (see open man page)  */
    fcntl(fdesc, F_SETFL, O_ASYNC);

    /* Set new port settings */
    newtio.c_cflag = baudrate | SERIAL_CONTROL;
    /* Input settings */
    if (parity == 0)
      {
        newtio.c_iflag = IGNPAR | SERIAL_INPUT;
      }
    else
      {
        newtio.c_iflag = SERIAL_INPUT;
      }

    tcflush(fdesc, TCIFLUSH);
    tcflush(fdesc, TCOFLUSH);
    tcsetattr(fdesc, TCSANOW, &newtio);

    return fdesc;
  }

#ifdef __cplusplus
}
#endif
robotics/computing/linux_asynchronous_serial_programming_how_to.1297264882.txt.gz · Dernière modification: 2012/09/20 10:52 (modification externe)