P. 1
Serial Programming HOWTO

Serial Programming HOWTO

|Views: 0|Likes:
Published by Hector Cabrera
Serial Programming on POSIX SO
Serial Programming on POSIX SO

More info:

Published by: Hector Cabrera on Apr 20, 2013
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

04/20/2013

pdf

text

original

Serial Programming HOWTO

Gary Frerking
gary@frerking.org

Peter Baumann
Revision History Revision 1.01 2001−08−26 New maintainer, converted to DocBook Revision 1.0 1998−01−22 Initial document release Revised by: glf Revised by: phb

This document describes how to program communications with devices over a serial port on a Linux box.

..................................................................3..............3 2................4 3......1 1.................1 1..............................................9 3.......... Disclaimer...........................8 3..............................................11 4............................................. Asynchronous Input...........................................5............................................................. Waiting for Input from Multiple Sources..............................................................6 3...........................................................4............................4............................................................2 1.... Program Examples .........................................................1... Non−Canonical Input Processing.......3 2........................................................................................................................................................................1.............................................................................................................................................. Canonical Input Processing...............2...........3 2......................................................................... Asynchronous Input....... Port Settings................... Credits................................................................................. Waiting for Input from Multiple Sources..........3................................................ Other Sources of Information......................................................................... Introduction.............................................................1 1........2.2.....2.........2 1........ Non−Canonical Input Processing........4 2................................................................................................ Debugging......4 2.....4 2................................. New Versions..................3..............................................................................13 i ......................................................................................... Getting started............................................Serial Programming HOWTO Table of Contents 1...................................... Copyright Information.............................. Input Concepts for Serial Devices.............................1.........................................3...................................................................................4 2....................................1.............................3.....6 3.................................................................................................... Feedback..............................................................4...................................... Canonical Input Processing ...............................................................................3...3..2 2...................................3.......

1. the author would like to be notified of any such distributions. you've gotten your wish. asyncronous I/O. there may be errors and inaccuracies. 1. stated below. Proceed with caution. or aggregate works incorporating any Linux HOWTO documents must be covered under this copyright notice.2. Disclaimer No liability for the contents of this documents can be accepted. The primary purpose of this update is to change the author information and convert the document to DocBook format. as long as this copyright notice is retained on all copies. 1. unless specifically noted otherwise. Use of a term in this document should not be regarded as affecting the validity of any trademark or service mark. very little if anything has changed at this time. Copyright Information This document is copyrighted (c) 1997 Peter Baumann. In short. Different techniques are explained: Canonical I/O (only complete lines are transmitted/received).1. please contact the Linux HOWTO coordinator at the address given below. In terms of technical content. If you have any questions. Unless otherwise stated. All about how to program communications with other devices / computers over a serial line under Linux. derivative works. (c) 2001 Gary Frerking and is distributed under the terms of the Linux Documentation Project (LDP) license. we do wish to retain copyright on the HOWTO documents. and although this is highly unlikely. examples and other content at your own risk. and waiting for input from multiple sources. Linux HOWTO documents are copyrighted by their respective authors. the author(s) do not take any responsibility for that. Sweeping changes to the technical content aren't going to happen overnight. Please send me any and all feedback you have. that may of course be damaging to your system. All examples were tested using a i386 Linux Kernel 2. and would like to be notified of any plans to redistribute the HOWTOs. Commercial redistribution is allowed and encouraged. Introduction 1 . Use the concepts. All translations.unc. This is the first update to the initial release of the Linux Serial Programming HOWTO. Exceptions to these rules may be granted under certain conditions.edu> 1. Linux HOWTO documents may be reproduced and distributed in whole or in part. you may not produce a derivative work from a HOWTO and impose additional restrictions on its distribution. please contact <linux−howto@metalab.29. we wish to promote dissemination of this information through as many channels as possible. it'd be very much appreciated.0. As this is a new edition of this document. All copyrights are held by their by their respective owners. but I'll work on it as much as time allows. however. That is. If you've been waiting in the wings for someone to take over this HOWTO. in any medium physical or electronic. Introduction This is the Linux Serial Programming HOWTO. However.

Strudthoff. Peter Waltenberg.3. 1. and Adrey Bonar.3. not much is new in terms of technical content yet. 1. You are strongly recommended to take a backup of your system before major installation and backups at regular intervals. Greg Hankins. comments and criticisms to the following email address : <gary@frerking. Michael Carter. Credits The original author thanked Mr.Serial Programming HOWTO Naming of particular products or brands should not be seen as endorsements.org>. this document wouldn't exist. 1. Feedback Feedback is most certainly welcome for this document. 1. New Versions 2 . Please send your additions.5. Without your submissions and input. Antonino Ianella. Michael Wiedmann. New Versions As previously mentioned. Sean Lincolne. Dave Pfaltzgraff.4.

Debugging The best way to debug your code is to set up another Linux box. 2.tar.4.2. If you use a multiport serial card. the port started loosing characters. The input mode flags in c_iflag handle all input processing. /* /* /* /* /* /* input mode flags */ output mode flags */ control mode flags */ local mode flags */ line discipline */ control characters */ This file also includes all flag definitions. Miniterm can be compiled very easily and will transmit all keyboard input raw over the serial port.g. Similarly c_oflag handles the output processing. cc_t c_cc[NCCS].2. If you free a serial port by disconnecting the mouse. and are configured for this use after startup. as the 2. Executing two programs on one computer just isn't fully asynchronous. Getting started 3 . which means that the characters sent from the device can be processed before they are read with read. Set it to ttyS0 for COM1. The characters input on one computer should appear on the other computer and vice versa. It is also possible to perform this testing with only one computer. the ports are configured to echo characters sent from the device back to it. tcflag_t c_cflag. Only the define statement #define MODEMDEVICE "/dev/ttyS0" has to be checked. c_cflag contains the settings for the port. and connect the two computers via a null−modem cable. Port Settings The devices /dev/ttyS* are intended to hook up terminals to your Linux box. To test your connection. cc_t c_line. if you have two unused serial ports. which normally has to be changed for data transmission. tcflag_t c_oflag. be sure to configure it correctly. E. You can then run two miniterms off two virtual consoles. tcflag_t c_lflag. All parameters can be easily configured from within a program. For a description of a cable see sect. When I connected to another computer. The configuration is stored in a structure struct termios. }. Getting started 2. ttyS1 for COM2. The input will not be echoed to the attached screen.gz in the examples directory) to transmit characters to your Linux box.edu/pub/Linux/docs/LDP/programmers−guide/lpg−0. To make a null−modem cable you have to cross the TxD (transmit) and RxD (receive) lines.unc. start miniterm on both computers and just type away.. etc. that all characters are transmitted raw (without output processing) over the line.h>: #define NCCS 19 struct termios { tcflag_t c_iflag. This has to be kept in mind when programming communication with a raw device. 7 of the Serial−HOWTO. I had mine configured wrong and everything worked fine as long as I was testing only on my computer.1. Use miniterm (available from the LDP programmers guide (ftp://sunsite. It is essential for testing. which is defined in <asm/termbits. remember to redirect /dev/mouse if it exists.

which means that a read will only return a full line of input.. until the read is satisfied.. or if the connected device sends bursts of characters.3. 2. Default values for the control characters are defined in <asm/termios. In my application I was handling input over a TCP/IP socket and input over a serial connection from another computer quasi−simultaneously. 2. signals are sent to your program. or an end of line character. This mode should be used if your application will always read a fixed number of characters. The program example given below will wait for input from two different input sources. etc.3. delete word.3. Finally the array c_cc defines the control characters for end of file. I lost characters.h>. and the program will then wait for new input. In asynchronous mode the read statement will return immediatly and send a signal to the calling program upon completion.2. stop. Non−Canonical Input Processing Non−Canonical Input Processing will handle a fixed amount of characters per read.3. but might be useful. Input Concepts for Serial Devices Here three different input concepts will be presented. etc. 2. Input Concepts for Serial Devices 4 . do not loop reading single characters to get a complete string. Waiting for Input from Multiple Sources This is not a different input mode. 2. The local mode flags stored in c_lflag determine if characters are echoed. if you are handling multiple devices..1. and allows for a character timer.Serial Programming HOWTO baudrate. etc. 2.. Canonical Input Processing This is the normal processing mode for terminals. it will be processed. whereas a read for the whole string did not show any errors.3. stop bits.4. The structure termios contains the c_line (line discipline) element. This signal can be received by a signal handler. Asynchronous Input The two modes described above can be used in synchronous and asynchronous mode. translate CR to NL. where a read statement will block. but can also be useful for communicating with other dl input is processed in units of lines. The appropriate concept has to be chosen for the intended application. etc. If input from one source becomes available. Canonical input processing can also handle the erase. When I did this.3. 2. and reprint characters. which is not used in POSIX compliant systems.3. A CR (the DOS/Windows default end−of−line) will not terminate a line with the default settings. The flags are described in the manual page termios(3). Synchronous is the default. bits per character. an end of file. Whenever possible. A line is by default terminated by a NL (ASCII LF).

Input Concepts for Serial Devices 5 .Serial Programming HOWTO The approach presented below seems rather complex. whereas looping until input becomes available would slow down other processes executing at the same time.3. 2. The select system call will not load the CPU while waiting for input. but it is important to keep in mind that Linux is a multi−processing operating system.

CRTSCTS : output hardware flow control (only used if the cable has all necessary lines. g. main() { int fd. */ fd = open(MODEMDEVICE.h> <stdio.h> <termios.h> <sys/stat. /* save current serial port settings */ bzero(&newtio.h>. 7 of Serial−HOWTO) CS8 : 8n1 (8bit.no parity.c. O_RDWR | O_NOCTTY ). Program Examples 6 . The type ahead buffer is limited to 255 characters. Canonical Input Processing #include #include #include #include #include <sys/types. You could also use cfsetispeed and cfsetospeed.newtio.h> or <posix1_lim.: chmod a+rw /dev/ttyS1)! 3.1. I hope that the code is understandable. The example for canonical input is commented best. See sect.&oldtio). } tcgetattr(fd.h> /* baudrate settings are defined in <asm/termbits. res. the other examples are commented only where they differ from the example for canonical input to emphasize the differences. struct termios oldtio. /* Open modem device for reading and writing and not as controlling tty because we don't want to get killed if linenoise sends CTRL−C. if (fd <0) {perror(MODEMDEVICE). See the comments in the code for explanation of the use of the different input modes. Program Examples All examples have been derived from miniterm. exit(−1). sizeof(newtio)). Don't forget to give the appropriate serial ports the right permissions (e.c.1 stopbit) 3. /* clear struct for new port settings */ /* BAUDRATE: Set bps rate.h> */ #define BAUDRATE B38400 /* change this definition for the correct port */ #define MODEMDEVICE "/dev/ttyS1" #define _POSIX_SOURCE 1 /* POSIX compliant source */ #define FALSE 0 #define TRUE 1 volatile int STOP=FALSE. just like the maximum string length for canonical input processing (<linux/limits. char buf[255]. The descriptions are not complete. but you are encouraged to experiment with the examples to derive the best solution for your application.h>). which is included by <termios.h> <fcntl.3.

/* IGNPAR ICRNL : ignore bytes with parity errors : map CR to NL (otherwise a CR input on the other computer will not terminate input) otherwise make device raw (no other input processing) */ newtio. If the number of characters read is smaller than the number of chars available.c_cc[VINTR] newtio. no modem contol : enable receiving characters */ newtio. 0. /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* Ctrl−c */ Ctrl−\ */ del */ @ */ Ctrl−d */ inter−character timer unused */ blocking read until 1 character arrives */ '\0' */ Ctrl−q */ Ctrl−s */ Ctrl−z */ '\0' */ Ctrl−r */ Ctrl−u */ Ctrl−w */ Ctrl−v */ '\0' */ 3. 0. 0. 0. */ while (STOP==FALSE) { /* loop until we have a terminating condition */ /* read blocks program execution until a line terminating character is input.c_cc[VREPRINT] newtio.&newtio). 1. /* terminal settings done. and don't send signals to calling program */ newtio.c_cc[VSTART] newtio. 0.c_cc[VEOL2] /* now clean the modem line and activate the settings for the port */ tcflush(fd.c_cc[VEOF] newtio.c_cc[VSTOP] newtio. TCIFLUSH).c_cc[VLNEXT] newtio. now handle input In this example.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD. /* ICANON : enable canonical input disable all echo functionality.c_lflag = ICANON.c_cc[VSWTC] newtio.h.c_cc[VSUSP] newtio. but we don't need them here */ newtio. 4. 0. Program Examples 7 .c_oflag = 0.Serial Programming HOWTO CLOCAL CREAD : local connection.c_cc[VMIN] newtio.c_cc[VERASE] newtio.c_cc[VEOL] newtio. 0. 0.c_cc[VKILL] newtio.TCSANOW. even if more than 255 chars are input. and are given in the comments. 0. 0.c_cc[VDISCARD] newtio. 0. /* Raw output.c_iflag = IGNPAR | ICRNL.c_cc[VQUIT] newtio.c_cc[VWERASE] newtio. /* initialize all control characters default values can be found in /usr/include/termios. tcsetattr(fd. 0.c_cc[VTIME] newtio. 0. = = = = = = = = = = = = = = = = = 0. 0. inputting a 'z' at the beginning of a line will exit the program. */ newtio.

If TIME is exceeded.255).2. res). buf. As TIME is zero. Non−Canonical Input Processing In non−canonical input processing mode. TIME serves as an inter−character timer. or the time between two characters exceeds TIME.c_cc[VMIN] all modes described above can be tested.h> <stdio. Two parameters control the behavior of this mode: c_cc[VTIME] sets the character timer. kill. etc. F_SETFL. The number of characters currently available. before reading to get the same result. The read will be satisfied if MIN characters are received. /* set end of string. or the number of characters requested will be returned. } 3. #include #include #include #include #include #define #define #define #define #define <sys/types. By modifying newtio. The read will be satisfied if a single character is read. Non−Canonical Input Processing 8 . so we can printf */ printf(":%s:%d\n". or TIME is exceeded (t = TIME *0.buf. buf[res]=0. If MIN > 0 and TIME > 0. you could issue a fcntl(fd. If MIN = 0 and TIME > 0. } /* restore the old port settings */ tcsetattr(fd. FNDELAY). According to Antonino (see contributions).c. input is not assembled into lines and input processing (erase. 3. the timer is not used.TCSANOW. no character will be returned. read will be satisfied immediately.Serial Programming HOWTO subsequent reads will return the remaining chars.) does not occur. If MIN > 0 and TIME = 0. if (buf[0]=='z') STOP=TRUE.&oldtio).2. TIME serves as a timeout value. delete. res will be set to the actual number of characters actually read */ res = read(fd. main() { int fd.h> BAUDRATE B38400 MODEMDEVICE "/dev/ttyS1" _POSIX_SOURCE 1 /* POSIX compliant source */ FALSE 0 TRUE 1 volatile int STOP=FALSE.c_cc[VTIME] and newtio. MIN sets the number of characters to receive before the read is satisfied.h> <fcntl.h> <sys/stat. If MIN = 0 and TIME = 0. The timer is restarted every time a character is received and only becomes active after the first character has been received. res.h> <termios.1 s). and c_cc[VMIN] sets the minimum number of characters to receive before satisfying the read.

c_iflag newtio.3.h> <sys/types. exit(−1).255).TCSANOW.. if (buf[0]=='z') STOP=TRUE. buf.&oldtio).. } 3. void signal_handler_IO (int status).newtio. } tcsetattr(fd. Asynchronous Input 9 . main() { int fd. tcsetattr(fd.. = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD. char buf[255]. /* definition of signal handler */ /* TRUE while no signal received */ /* definition of signal action */ 3. res.c_lflag = 0..buf.c.h> BAUDRATE B38400 MODEMDEVICE "/dev/ttyS1" _POSIX_SOURCE 1 /* POSIX compliant source */ FALSE 0 TRUE 1 volatile int STOP=FALSE.) */ newtio. int wait_flag=TRUE. */ printf(":%s:%d\n". newtio. = 0. /* so we can printf.3. /* inter−character timer unused */ /* blocking read until 5 chars received */ tcflush(fd. if (fd <0) {perror(MODEMDEVICE). = IGNPAR.h> <stdio. newtio.&oldtio). res). struct sigaction saio. = 5. TCIFLUSH).c_cc[VMIN] = 0.h> <sys/signal. } tcgetattr(fd.&newtio). /* set input mode (non−canonical.c_cflag newtio..h> <fcntl.h> <unistd.newtio. /* save current port settings */ bzero(&newtio. O_RDWR | O_NOCTTY ). Asynchronous Input #include #include #include #include #include #include #define #define #define #define #define <termios.TCSANOW. no echo.c_oflag sizeof(newtio)). struct termios oldtio. char buf[255].c_cc[VTIME] newtio. /* returns after 5 chars have been input */ buf[res]=0.Serial Programming HOWTO struct termios oldtio. while (STOP==FALSE) { /* loop for input */ res = read(fd. fd = open(MODEMDEVICE.

* ***************************************************************************/ void signal_handler_IO (int status) { printf("received SIGIO signal.&oldtio). if (res==1) STOP=TRUE. } 3.. FASYNC). TCIFLUSH).c_cc[VMIN]=1. saio.c_lflag = ICANON. Asynchronous Input 10 . } /* install the signal handler before making the device asynchronous */ saio.3. exit(−1).\n"). /* allow the process to receive SIGIO */ fcntl(fd.\n"). wait_flag = FALSE. tcflush(fd. /* loop while waiting for input.&oldtio).Serial Programming HOWTO /* open the device to be non−blocking (read will return immediatly) */ fd = open(MODEMDEVICE. sets wait_flag to FALSE. /* save current port settings */ /* set new port settings for canonical input processing */ newtio. newtio.sa_handler = signal_handler_IO. /* after receiving SIGIO.sa_restorer = NULL. buf. sigaction(SIGIO. saio. /* wait for new input */ } } /* restore old port settings */ tcsetattr(fd.c_iflag = IGNPAR | ICRNL.sa_mask = 0. /* Make the file descriptor asynchronous (the manual page says only O_APPEND and O_NONBLOCK. newtio. O_RDWR | O_NOCTTY | O_NONBLOCK). F_SETOWN.usleep(100000).c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD. input is available and can be read */ if (wait_flag==FALSE) { res = read(fd.c_oflag = 0. newtio.TCSANOW. buf[res]=0.&saio. F_SETFL.255). will work with F_SETFL. saio. /* stop loop if only a CR was input */ wait_flag = TRUE. to indicate above loop that * * characters have been received. normally we would do something useful here */ while (STOP==FALSE) { printf(".) */ fcntl(fd.buf.sa_flags = 0.NULL). } /*************************************************************************** * signal handler.&newtio). printf(":%s:%d\n". wait_flag = FALSE. getpid()).. res).c_cc[VTIME]=0. tcsetattr(fd. if (fd <0) {perror(MODEMDEVICE). newtio. newtio. tcgetattr(fd.TCSANOW.

All handling of fd_set is done with the provided macros. fd2)+1. */ 3. /* milliseconds */ Timeout. &Timeout). This will not only work with serial ports. NULL. &readfs. maxfd = MAX (fd1. &readfs). if (res==0) /* number of file descriptors with input = 0. and returns a file descriptor */ fd1 = open_input_source("/dev/ttyS1"). &readfs. but with any set of file descriptors. if (FD_ISSET(fd1)) /* input from source 1 available */ handle_input_from_source1(). fd2. NULL). which has a bit entry for every valid file descriptor number.h> #include <unistd. readfs. It is just intended to be a hint. /* maximum bit entry (fd) to test */ /* loop for input */ while (loop) { FD_SET(fd1. output. #include <sys/time. /* set timeout value within input loop */ Timeout. /* seconds */ res = select(maxfd. This is a bit array. NULL. NULL. NULL.h> main() { int fd_set int int fd1. If you need to timeout on input. See also the manual page select(2). sets the port correctly. if (FD_ISSET(fd2)) /* input from source 2 available */ handle_input_from_source2(). } } The given example blocks indefinitely.Serial Programming HOWTO 3. maxfd. Waiting for Input from Multiple Sources This section is kept to a minimum. &readfs). /* set testing for source 2 */ /* block until input becomes available */ select(maxfd.4.4. /* set testing for source 1 */ FD_SET(fd2. struct timeval Timeout. fd2 = open_input_source("/dev/ttyS2"). /* COM3 */ if (fd2<0) exit(0). timeout occurred. and therefore the example code is kept short. in which the bits for the file descriptors are set where input. just replace the select call by: int res.tv_sec = 1. /* COM2 */ if (fd1<0) exit(0). /* /* /* /* input sources 1 and 2 */ file descriptor set */ maximum file desciptor used */ loop while TRUE */ /* open_input_source opens a device.tv_usec = 0. loop=1. The select call and accompanying macros use a fd_set.h> #include <sys/types. or an exception occurred. until input from one of the sources becomes available. select will accept a fd_set with the bits set for the relevant file descriptors and returns a fd_set. Waiting for Input from Multiple Sources 11 .

4. but beware that Timeout is decremented by the time actually waited for input by select.Serial Programming HOWTO This example will timeout after 1 second. 3. select will return immediatly. If the timeout value is zero. If a timeout occurs. select will return 0. Waiting for Input from Multiple Sources 12 .

• The manual page termios(3) describes all flags for the termios structure.4. 4. by Michael Sweet. • Serial Programming Guide for POSIX Compliant Operating Systems. Other Sources of Information • The Linux Serial−HOWTO describes how to set up serial ports and contains hardware information. Other Sources of Information 13 .

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->