Outils pour utilisateurs

Outils du site


en:robotics:computing:linux_asynchronous_serial_programming_how_to

Différences

Cette page vous affiche les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue comparative

en:robotics:computing:linux_asynchronous_serial_programming_how_to [2011/10/10 17:38]
gdo removed
— (Version actuelle)
Ligne 1: Ligne 1:
-====== Introduction ====== 
  
-This article describes asynchrous serial programming using signal handler. 
- 
-== References == 
-  * Serial Programming HOWTO : [[http://​tldp.org/​HOWTO/​Serial-Programming-HOWTO/​]] 
- 
-== Hardware used : == 
-  * A desktop PC. 
-  * An internet connection. 
- 
-== Softwares : == 
-  * Ubuntu 10.10 installed : [[http://​www.ubuntu.com/​]] 
-  * Package **build-essential** and **socat** 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** : 
-<​code>#​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) 
-#define NO_PARITY_CHECK 0 
-#define PARITY_CHECK ​   1 
- 
-  /* 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</​code>​ 
- 
-And the source file **serialCom.c** with more explanations in code comments : 
-<​code>#​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 == NO_PARITY_CHECK) 
-      { 
-        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</​code>​ 
- 
-To generate the library : 
-<​code>​$ gcc -o libSerialCom.so --shared serialCom.c -I.</​code>​ 
- 
-====== Test program ====== 
- 
-Here is a little test program **testSerialCom.cpp** which just print the byte it received, reading bytes one by one. 
-We use C++ there just to show the lib is usable with C/C++ project. 
-Explanations are in code comments : 
- 
-<​code>​using namespace std; 
- 
-#include <​iostream>​ 
-#include <​serialCom.h>​ 
- 
-/* Flag indicating datas are ready to be read */ 
-static bool flag = false; 
- 
-/* SIGIO handler */ 
-void 
-my_handler(int status) 
-{ 
-  /* Data ready to be read */ 
-  flag = true; 
-} 
- 
-/* MAIN */ 
-int 
-main(int argc, char **argv) 
-{ 
-  /* Initialize the serial communication */ 
-  int fdesc = serialConfiguration(my_handler,​ "/​dev/​ttyS0",​ B115200, 
-      NO_PARITY_CHECK);​ 
- 
-  /* Data buffer */ 
-  char buf; 
-  /* Reading result */ 
-  int res = 0; 
- 
-  /* Initialize data flag */ 
-  flag = false; 
- 
-  while (buf != '​\t'​) 
-    { 
-      /* If there is a data to be read */ 
-      if (flag == true) 
-        { 
-          /* Read one byte */ 
-          do 
-            { 
-              res = read(fdesc, &buf, 1); 
-              cout << buf << endl; 
-            } 
-          while (res > 0); 
- 
-          flag = false; 
-        } 
-    } 
- 
-  return 0; 
-}</​code>​ 
- 
-To generate the binary : 
-<​code>​$ g++ -o testSerialCom testserialcom.cpp -I../​../​SerialCom/​ -L../​../​SerialCom/​ -lSerialCom</​code>​ 
- 
-====== Performing the test ====== 
- 
-If you have no serial port to test your code, just create two virtual ports with **socat** in a terminal. : 
- 
-<​code>​$ socat -d -d PTY: PTY: 
-2011/02/17 23:58:36 socat[12866] N PTY is /dev/pts/3 
-2011/02/17 23:58:36 socat[12866] N PTY is /dev/pts/4 
-2011/02/17 23:58:36 socat[12866] N starting data transfer loop with FDs [3,3] and [5,​5]</​code>​ 
- 
-Before launching test program, do not forget to change the port asked in the main function of the **testSerialCom.c**. And rebuild your program. 
-Then in an other terminal just launch the test program : 
- 
-<​code>​$ sudo LD_LIBRARY_PATH=../​SerialCom/​ ./​testSerialCom</​code>​ 
- 
-And finally run **cutecom** with following parameters : 
- 
-{{:​robotics:​computing:​linux_asynchronous_serial_programming:​cutecom.png|}} 
- 
-To test just type some characters on **cutecom** input, you must see them appear on the test program terminal. :) 
en/robotics/computing/linux_asynchronous_serial_programming_how_to.1318261130.txt.gz · Dernière modification: 2012/09/20 10:53 (modification externe)