How to Use Serialport Read in C#
Series Programming Guide for POSIX Operating Systems
5th Edition
Michael R. Sweet
Copyright 1994-1999, All Rights Reserved.
Table of Contents
Introduction
Chapter 1, Basics of Serial Communications
- What Are Serial Communications?
- What Is RS-232?
- Bespeak Definitions
- Asynchronous Communications
- What Are Total Duplex and Half Duplex?
- Period Control
- What Is a Interruption?
- Synchronous Communications
- Accessing Serial Ports
- Series Port Files
- Opening a Serial Port
- Writing Data to the Port
- Reading Data from the Port
- Endmost a Serial Port
- The POSIX Final Interface
- Control Options
- Local Options
- Input Options
- Output Options
- Control Characters
- What Is a MODEM?
- Communicating With a MODEM
- Standard MODEM Commands
- Mutual MODEM Communication Problems
- Series Port IOCTLs
- Getting the Command Signals
- Setting the Control Signals
- Getting the Number of Bytes Bachelor
- Selecting Input from a Serial Port
- The SELECT Organisation Phone call
- Using the SELECT System Telephone call
- Using SELECT with the Ten Intrinsics Library
- RS-232 Pinouts
- RS-422 Pinouts
- RS-574 (IBM PC/AT) Pinouts
- SGI Pinouts
- Command Codes
Introduction
The Serial Programming Guide for POSIX Operating Systems volition teach you how to successfully, efficiently, and portably program the serial ports on your UNIX® workstation or PC. Each chapter provides programming examples that employ the POSIX (Portable Standard for UNIX) terminal control functions and should work with very few modifications under IRIX®, HP-UX, SunOS®, Solaris®, Digital UNIX®, Linux®, and near other UNIX operating systems. The biggest departure between operating systems that you will observe is the filenames used for series port device and lock files.
This guide is organized into the following capacity and appendices:
- Affiliate 1, Basics of Serial Programming
- Chapter 2, Configuring the Serial Port
- Chapter iii, Talking to MODEMs
- Chapter 4, Advanced Serial Programming
- Appendix A, RS-232 Pinouts
- Appendix B, ASCII Command Codes
Chapter ane, Basics of Series Communications
This chapter introduces serial communications, RS-232 and other standards that are used on virtually computers as well as how to admission a series port from a C program.
What Are Series Communications?
Computers transfer data (information) one or more than $.25 at a time. Series refers to the transfer of data ane chip at a time. Serial communications include most network devices, keyboards, mice, MODEMs, and terminals.
When doing serial communications each word (i.e. byte or character) of data yous send or receive is sent one bit at a time. Each bit is either on or off. The terms you'll hear sometimes are mark for the on state and space for the off land.
The speed of the serial data is well-nigh ofttimes expressed as bits-per-second ("bps") or baudot rate ("baud"). This simply represents the number of ones and zeroes that can be sent in i second. Back at the dawn of the computer age, 300 baud was considered fast, just today computers tin can handle RS-232 speeds every bit high as 430,800 baud! When the baud charge per unit exceeds one,000, y'all'll usually see the rate shown in kilo baud, or kbps (e.g. 9.6k, nineteen.2k, etc). For rates above 1,000,000 that rate is shown in megabaud, or Mbps (east.g. 1.5Mbps).
When referring to serial devices or ports, they are either labeled as Data Communications Equipment ("DCE") or Information Final Equipment ("DTE"). The difference between these is simple - every signal pair, like transmit and receive, is swapped. When connecting two DTE or two DCE interfaces together, a serial null-MODEM cable or adapter is used that swaps the signal pairs.
What Is RS-232?
RS-232 is a standard electrical interface for serial communications divers by the Electronic Industries Clan ("EIA"). RS-232 really comes in three different flavors (A, B, and C) with each one defining a unlike voltage range for the on and off levels. The most commonly used variety is RS-232C, which defines a mark (on) bit equally a voltage betwixt -3V and -12V and a space (off) scrap as a voltage between +3V and +12V. The RS-232C specification says these signals tin can go nearly 25 feet (8m) before they get unusable. You tin usually send signals a chip farther than this as long equally the baud is low enough.
Besides wires for incoming and outgoing data, there are others that provide timing, status, and handshaking:
| Pin | Description | Pin | Description | Pivot | Clarification | Pin | Description | Pin | Description |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Globe Ground | six | DSR - Information Set up Set | 11 | Unassigned | 16 | Secondary RXD | 21 | Indicate Quality Detect |
| 2 | TXD - Transmitted Data | vii | GND - Logic Ground | 12 | Secondary DCD | 17 | Receiver Clock | 22 | Ring Detect |
| 3 | RXD - Received Data | viii | DCD - Information Carrier Detect | 13 | Secondary CTS | 18 | Unassigned | 23 | Data Charge per unit Select |
| 4 | RTS - Asking To Ship | nine | Reserved | fourteen | Secondary TXD | 19 | Secondary RTS | 24 | Transmit Clock |
| v | CTS - Clear To Send | x | Reserved | 15 | Transmit Clock | 20 | DTR - Data Last Set up | 25 | Unassigned |
Two standards for series interfaces yous may besides see are RS-422 and RS-574. RS-422 uses lower voltages and differential signals to let cablevision lengths upwardly to about 1000ft (300m). RS-574 defines the 9-pin PC series connector and voltages.
Point Definitions
The RS-232 standard defines some xviii dissimilar signals for serial communications. Of these, only six are generally available in the UNIX environment.
GND - Logic Ground
Technically the logic footing is not a signal, just without it none of the other signals will operate. Basically, the logic basis acts as a reference voltage so that the electronics know which voltages are positive or negative.
TXD - Transmitted Information
The TXD signal carries data transmitted from your workstation to the computer or device on the other end (similar a MODEM). A mark voltage is interpreted as a value of one, while a space voltage is interpreted every bit a value of 0.
RXD - Received Data
The RXD signal carries information transmitted from the calculator or device on the other end to your workstation. Like TXD, mark and space voltages are interpreted as one and 0, respectively.
DCD - Data Carrier Discover
The DCD indicate is received from the computer or device on the other end of your serial cable. A space voltage on this signal line indicates that the computer or device is currently connected or on line. DCD is non ever used or available.
DTR - Data Terminal Fix
The DTR signal is generated by your workstation and tells the computer or device on the other end that you are prepare (a space voltage) or not-fix (a mark voltage). DTR is usually enabled automatically whenever you lot open up the serial interface on the workstation.
CTS - Clear To Ship
The CTS signal is received from the other end of the series cable. A infinite voltage indicates that is alright to send more than serial data from your workstation.
CTS is ordinarily used to regulate the flow of serial data from your workstation to the other terminate.
RTS - Request To Ship
The RTS betoken is fix to the space voltage past your workstation to indicate that more than data is set up to be sent.
Like CTS, RTS helps to regulate the menstruum of information between your workstation and the reckoner or device on the other end of the serial cable. Most workstations leave this signal set to the space voltage all the time.
Asynchronous Communications
For the figurer to understand the series data coming into it, it needs some way to make up one's mind where 1 character ends and the next begins. This guide deals exclusively with asynchronous serial data.
In asynchronous mode the series data line stays in the mark (1) state until a character is transmitted. A start bit preceeds each graphic symbol and is followed immediately by each scrap in the grapheme, an optional parity bit, and one or more stop bits. The kickoff bit is always a space (0) and tells the computer that new serial data is bachelor. Data can be sent or received at any time, thus the name asynchronous.
Figure 1 - Asynchronous Data Transmission
The optional parity scrap is a unproblematic sum of the data bits indicating whether or non the data contains an even or odd number of i bits. With fifty-fifty parity, the parity bit is 0 if in that location is an even number of 1's in the character. With odd parity, the parity bit is 0 if there is an odd number of ane'due south in the data. You may likewise hear the terms space parity, marking parity, and no parity. Space parity ways that the parity flake is e'er 0, while marking parity means the flake is always one. No parity ways that no parity bit is nowadays or transmitted.
The remaining $.25 are called end bits. There can be 1, 1.5, or 2 end bits between characters and they always take a value of 1. Terminate bits traditionally were used to give the computer time to process the previous graphic symbol, but now only serve to synchronize the receiving computer to the incoming characters.
Asynchronous data formats are usually expressed as "8N1", "7E1", and so along. These stand for "eight data $.25, no parity, 1 stop bit" and "7 data bits, even parity, 1 stop flake" respectively.
What Are Full Duplex and Half Duplex?
Total duplex means that the computer can send and receive data simultaneously - in that location are two separate information channels (1 coming in, one going out).
Half duplex means that the computer cannot ship or receive data at the aforementioned time. Ordinarily this means there is only a single information channel to talk over. This does not mean that whatsoever of the RS-232 signals are not used. Rather, it usually means that the communications link uses some standard other than RS-232 that does non support full duplex operation.
Flow Control
It is frequently necessary to regulate the flow of information when transferring information between 2 series interfaces. This can be due to limitations in an intermediate serial communications link, one of the serial interfaces, or some storage media. Two methods are commonly used for asynchronous information.
The outset method is often called "software" menses control and uses special characters to start (XON or DC1, 021 octal) or stop (XOFF or DC3, 023 octal) the menses of information. These characters are defined in the American Standard Code for Data Interchange ("ASCII"). While these codes are useful when transferring textual information, they cannot exist used when transferring other types of information without special programming.
The 2nd method is called "hardware" catamenia control and uses the RS-232 CTS and RTS signals instead of special characters. The receiver sets CTS to the infinite voltage when information technology is ready to receive more than data and to the mark voltage when it is not gear up. As well, the sender sets RTS to the space voltage when it is ready to send more data. Considering hardware flow control uses a separate set of signals, information technology is much faster than software menstruum command which needs to send or receive multiple bits of information to exercise the same thing. CTS/RTS period command is not supported past all hardware or operating systems.
What Is a Intermission?
Normally a receive or transmit information signal stays at the mark voltage until a new character is transferred. If the signal is dropped to the infinite voltage for a long period of time, unremarkably one/4 to ane/ii second, then a break condition is said to exist.
A break is sometimes used to reset a communications line or change the operating manner of communications hardware like a MODEM. Chapter three, Talking to MODEMs covers these applications in more depth.
Synchronous Communications
Dissimilar asynchronous information, synchronous data appears every bit a constant stream of bits. To read the information on the line, the computer must provide or receive a mutual flake clock so that both the sender and receiver are synchronized.
Even with this synchronization, the computer must mark the kickoff of the data somehow. The near common way of doing this is to utilize a data packet protocol like Serial Data Link Control ("SDLC") or Loftier-Speed Data Link Control ("HDLC").
Each protocol defines certain bit sequences to represent the outset and cease of a data packet. Each likewise defines a chip sequence that is used when there is no data. These bit sequences allow the calculator encounter the offset of a information packet.
Considering synchronous protocols do not use per-character synchronization $.25 they typically provide at least a 25% improvement in operation over asynchronous communications and are suitable for remote networking and configurations with more than than ii serial interfaces.
Despite the speed advantages of synchronous communications, near RS-232 hardware does not support it due to the extra hardware and software required.
Accessing Serial Ports
Like all devices, UNIX provides access to serial ports via device files. To admission a serial port you but open the respective device file.
Serial Port Files
Each serial port on a UNIX organisation has one or more than device files (files in the /dev directory) associated with it:
| System | Port one | Port 2 |
|---|---|---|
| IRIX® | /dev/ttyf1 | /dev/ttyf2 |
| HP-UX | /dev/tty1p0 | /dev/tty2p0 |
| Solaris®/SunOS® | /dev/ttya | /dev/ttyb |
| Linux® | /dev/ttyS0 | /dev/ttyS1 |
| Digital UNIX® | /dev/tty01 | /dev/tty02 |
Opening a Serial Port
Since a serial port is a file, the open(2) function is used to access it. The one hitch with UNIX is that device files are usually not accessable by normal users. Workarounds include changing the access permissions to the file(south) in question, running your program as the super-user (root), or making your program set up-userid so that it runs every bit the owner of the device file.
For at present we'll assume that the file is accessable past all users. The code to open serial port 1 on an sgi® workstation running IRIX is:
List ane - Opening a series port.
#include <stdio.h> /* Standard input/output definitions */ #include <string.h> /* String role definitions */ #include <unistd.h> /* UNIX standard function definitions */ #include <fcntl.h> /* File control definitions */ #include <errno.h> /* Error number definitions */ #include <termios.h> /* POSIX terminal control definitions */ /* * 'open_port()' - Open serial port ane. * * Returns the file descriptor on success or -1 on error. */ int open_port(void) { int fd; /* File descriptor for the port */ fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { /* * Could not open the port. */ perror("open_port: Unable to open /dev/ttyf1 - "); } else fcntl(fd, F_SETFL, 0); return (fd); } Other systems would require the respective device file name, merely otherwise the code is the same.
Open Options
Yous'll notice that when we opened the device file nosotros used 2 other flags along with the read+write mode:
fd = open up("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY); The O_NOCTTY flag tells UNIX that this program doesn't want to exist the "decision-making final" for that port. If y'all don't specify this and then whatsoever input (such as keyboard arrest signals and so forth) volition bear upon your process. Programs like getty(1M/8) use this feature when starting the login procedure, but normally a user program does not desire this behavior.
The O_NDELAY flag tells UNIX that this program doesn't care what country the DCD point line is in - whether the other terminate of the port is upwards and running. If yous do not specify this flag, your process volition be put to slumber until the DCD betoken line is the space voltage.
Writing Data to the Port
Writing data to the port is easy - simply use the write(two) organization call to send data it:
n = write(fd, "ATZ\r", 4); if (n < 0) fputs("write() of iv bytes failed!\northward", stderr); The write function returns the number of bytes sent or -1 if an fault occurred. Commonly the only error you'll see is EIO when a MODEM or data link drops the Data Carrier Detect (DCD) line. This condition volition persist until yous close the port.
Reading Data from the Port
Reading information from a port is a niggling trickier. When you operate the port in raw information fashion, each read(2) organisation phone call will return however many characters are actually available in the serial input buffers. If no characters are bachelor, the phone call will block (wait) until characters come in, an interval timer expires, or an mistake occurs. The read part tin can be made to return immediately by doing the following:
fcntl(fd, F_SETFL, FNDELAY);
The FNDELAY option causes the read function to return 0 if no characters are bachelor on the port. To restore normal (blocking) behavior, telephone call fcntl() without the FNDELAY option:
fcntl(fd, F_SETFL, 0);
This is also used after opening a series port with the O_NDELAY option.
Closing a Series Port
To close the serial port, but use the close organization phone call:
shut(fd);
Closing a series port volition also usually set the DTR indicate low which causes nearly MODEMs to hang upward.
Chapter 2, Configuring the Serial Port
This affiliate discusses how to configure a series port from C using the POSIX termios interface.
The POSIX Terminal Interface
Most systems back up the POSIX terminal (series) interface for changing parameters such as baud charge per unit, grapheme size, and so on. The first thing you need to do is include the file <termios.h>; this defines the terminal control structure every bit well every bit the POSIX control functions.
The two near important POSIX functions are tcgetattr(three) and tcsetattr(3). These get and ready terminal attributes, respectively; yous provide a pointer to a termios construction that contains all of the serial options available:
| Member | Description |
|---|---|
| c_cflag | Control options |
| c_lflag | Line options |
| c_iflag | Input options |
| c_oflag | Output options |
| c_cc | Control characters |
| c_ispeed | Input baud (new interface) |
| c_ospeed | Output baud (new interface) |
Control Options
The c_cflag member controls the baud charge per unit, number of data $.25, parity, stop bits, and hardware flow control. There are constants for all of the supported configurations.| Constant | Clarification |
|---|---|
| CBAUD | Bit mask for baud charge per unit |
| B0 | 0 baud (drib DTR) |
| B50 | 50 baud |
| B75 | 75 baud |
| B110 | 110 baud |
| B134 | 134.5 baud |
| B150 | 150 baud |
| B200 | 200 baud |
| B300 | 300 baud |
| B600 | 600 baud |
| B1200 | 1200 baud |
| B1800 | 1800 baud |
| B2400 | 2400 baud |
| B4800 | 4800 baud |
| B9600 | 9600 baud |
| B19200 | 19200 baud |
| B38400 | 38400 baud |
| B57600 | 57,600 baud |
| B76800 | 76,800 baud |
| B115200 | 115,200 baud |
| EXTA | External rate clock |
| EXTB | External rate clock |
| CSIZE | Bit mask for data bits |
| CS5 | 5 data bits |
| CS6 | 6 data bits |
| CS7 | 7 information $.25 |
| CS8 | 8 data $.25 |
| CSTOPB | 2 end bits (1 otherwise) |
| CREAD | Enable receiver |
| PARENB | Enable parity scrap |
| PARODD | Use odd parity instead of even |
| HUPCL | Hangup (drop DTR) on last close |
| CLOCAL | Local line - do not modify "owner" of port |
| LOBLK | Block job command output |
| CNEW_RTSCTS CRTSCTS | Enable hardware flow control (not supported on all platforms) |
The c_cflag fellow member contains two options that should e'er be enabled, CLOCAL and CREAD. These will ensure that your program does non become the 'owner' of the port field of study to sporatic job control and hangup signals, and as well that the series interface commuter will read incoming data bytes.
The baud rate constants (CBAUD, B9600, etc.) are used for older interfaces that lack the c_ispeed and c_ospeed members. Run into the next section for information on the POSIX functions used to set the baud charge per unit.
Never initialize the c_cflag (or any other flag) member directly; y'all should ever apply the bitwise AND, OR, and NOT operators to set or clear bits in the members. Different operating system versions (and even patches) can and do use the bits differently, so using the bitwise operators will prevent y'all from clobbering a fleck flag that is needed in a newer serial driver.
Setting the Baud Charge per unit
The baud rate is stored in different places depending on the operating organization. Older interfaces shop the baud rate in the c_cflag member using i of the baud rate constants in table 4, while newer implementations provide the c_ispeed and c_ospeed members that contain the actual baud rate value.
The cfsetospeed(3) and cfsetispeed(three) functions are provided to set the baud rate in the termios structure regardless of the underlying operating system interface. Typically you'd use the post-obit code to prepare the baud rate:
List ii - Setting the baud rate.
struct termios options; /* * Get the current options for the port... */ tcgetattr(fd, &options); /* * Fix the baud rates to 19200... */ cfsetispeed(&options, B19200); cfsetospeed(&options, B19200); /* * Enable the receiver and set local mode... */ options.c_cflag |= (CLOCAL | CREAD); /* * Set the new options for the port... */ tcsetattr(fd, TCSANOW, &options);
The tcgetattr(three) part fills the termios structure you provide with the electric current serial port configuration. After we set the baud rates and enable local mode and serial data receipt, we select the new configuration using tcsetattr(3). The TCSANOW constant specifies that all changes should occur immediately without waiting for output data to finish sending or input data to finish receiving. At that place are other constants to wait for input and output to finish or to flush the input and output buffers.
Most systems practise non support different input and output speeds, so be sure to set both to the same value for maximum portability.
| Constant | Description |
|---|---|
| TCSANOW | Make changes at present without waiting for data to complete |
| TCSADRAIN | Wait until everything has been transmitted |
| TCSAFLUSH | Flush input and output buffers and brand the change |
Setting the Character Size
Unlike the baud rate, at that place is no convienience function to set the character size. Instead you lot must do a little bitmasking to set things up. The character size is specified in bits:
options.c_cflag &= ~CSIZE; /* Mask the graphic symbol size $.25 */ options.c_cflag |= CS8; /* Select viii data bits */
Setting Parity Checking
Similar the grapheme size you must manually set the parity enable and parity type bits. UNIX serial drivers back up even, odd, and no parity bit generation. Space parity can be simulated with clever coding.
- No parity (8N1):
options.c_cflag &= ~PARENB options.c_cflag &= ~CSTOPB options.c_cflag &= ~CSIZE; options.c_cflag |= CS8;
options.c_cflag |= PARENB options.c_cflag &= ~PARODD options.c_cflag &= ~CSTOPB options.c_cflag &= ~CSIZE; options.c_cflag |= CS7;
options.c_cflag |= PARENB options.c_cflag |= PARODD options.c_cflag &= ~CSTOPB options.c_cflag &= ~CSIZE; options.c_cflag |= CS7;
options.c_cflag &= ~PARENB options.c_cflag &= ~CSTOPB options.c_cflag &= ~CSIZE; options.c_cflag |= CS8;
Setting Hardware Flow Control
Some versions of UNIX back up hardware catamenia control using the CTS (Clear To Send) and RTS (Request To Send) bespeak lines. If the CNEW_RTSCTS or CRTSCTS constants are defined on your system then hardware flow command is probably supported. Practise the following to enable hardware flow control:
options.c_cflag |= CNEW_RTSCTS; /* Also chosen CRTSCTS */
Similarly, to disable hardware catamenia command:
options.c_cflag &= ~CNEW_RTSCTS;
Local Options
The local modes member c_lflag controls how input characters are managed by the serial driver. In general you lot will configure the c_lflag member for canonical or raw input.
| Constant | Description |
|---|---|
| ISIG | Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals |
| ICANON | Enable canonical input (else raw) |
| XCASE | Map capital letter \lowercase (obsolete) |
| Echo | Enable echoing of input characters |
| ECHOE | Echo erase character as BS-SP-BS |
| ECHOK | Echo NL after impale character |
| ECHONL | Echo NL |
| NOFLSH | Disable flushing of input buffers afterwards interrupt or quit characters |
| IEXTEN | Enable extended functions |
| ECHOCTL | Repeat control characters as ^char and delete as ~? |
| ECHOPRT | Echo erased grapheme equally graphic symbol erased |
| ECHOKE | BS-SP-BS unabridged line on line kill |
| FLUSHO | Output being flushed |
| PENDIN | Retype pending input at next read or input char |
| TOSTOP | Send SIGTTOU for background output |
Choosing Canonical Input
Canonical input is line-oriented. Input characters are put into a buffer which can be edited interactively by the user until a CR (carriage return) or LF (line feed) character is received.
When selecting this fashion yous commonly select the ICANON, ECHO, and ECHOE options:
options.c_lflag |= (ICANON | Repeat | ECHOE);
Choosing Raw Input
Raw input is unprocessed. Input characters are passed through exactly as they are received, when they are received. Generally you'll deselect the ICANON, Echo, ECHOE, and ISIG options when using raw input:
options.c_lflag &= ~(ICANON | Repeat | ECHOE | ISIG);
A Annotation Near Input Repeat
Never enable input echo (Repeat, ECHOE) when sending commands to a MODEM or other calculator that is echoing characters, as you will generate a feedback loop between the two serial interfaces!
Input Options
The input modes member c_iflag controls any input processing that is done to characters received on the port. Like the c_cflag field, the final value stored in c_iflag is the bitwise OR of the desired options.
| Constant | Clarification |
|---|---|
| INPCK | Enable parity bank check |
| IGNPAR | Ignore parity errors |
| PARMRK | Mark parity errors |
| ISTRIP | Strip parity bits |
| IXON | Enable software menstruation control (outgoing) |
| IXOFF | Enable software period control (incoming) |
| IXANY | Permit any character to offset menses over again |
| IGNBRK | Ignore break condition |
| BRKINT | Ship a SIGINT when a break condition is detected |
| INLCR | Map NL to CR |
| IGNCR | Ignore CR |
| ICRNL | Map CR to NL |
| IUCLC | Map uppercase to lowercase |
| IMAXBEL | Echo BEL on input line as well long |
Setting Input Parity Options
You should enable input parity checking when y'all have enabled parity in the c_cflag fellow member (PARENB). The revelant constants for input parity checking are INPCK, IGNPAR, PARMRK , and ISTRIP. Generally you volition select INPCK and ISTRIP to enable checking and stripping of the parity bit:
options.c_iflag |= (INPCK | ISTRIP);
IGNPAR is a somewhat dangerous choice that tells the series driver to ignore parity errors and laissez passer the incoming data through as if no errors had occurred. This can be useful for testing the quality of a communications link, but in full general is not used for practical reasons.
PARMRK causes parity errors to be 'marked' in the input stream using special characters. If IGNPAR is enabled, a NUL grapheme (000 octal) is sent to your program earlier every character with a parity error. Otherwise, a DEL (177 octal) and NUL grapheme is sent forth with the bad character.
Setting Software Menstruum Control
Software menses control is enabled using the IXON, IXOFF , and IXANY constants:
options.c_iflag |= (IXON | IXOFF | IXANY);
To disable software menses command simply mask those bits:
options.c_iflag &= ~(IXON | IXOFF | IXANY);
The XON (offset information) and XOFF (stop data) characters are defined in the c_cc array described below.
Output Options
The c_oflag member contains output filtering options. Like the input modes, you can select processed or raw data output.
| Constant | Clarification |
|---|---|
| OPOST | Postprocess output (not prepare = raw output) |
| OLCUC | Map lowercase to uppercase |
| ONLCR | Map NL to CR-NL |
| OCRNL | Map CR to NL |
| NOCR | No CR output at column 0 |
| ONLRET | NL performs CR function |
| OFILL | Use fill characters for filibuster |
| OFDEL | Fill graphic symbol is DEL |
| NLDLY | Mask for delay time needed between lines |
| NL0 | No delay for NLs |
| NL1 | Delay further output after newline for 100 milliseconds |
| CRDLY | Mask for delay time needed to return carriage to left cavalcade |
| CR0 | No filibuster for CRs |
| CR1 | Delay after CRs depending on electric current cavalcade position |
| CR2 | Delay 100 milliseconds after sending CRs |
| CR3 | Filibuster 150 milliseconds after sending CRs |
| TABDLY | Mask for delay time needed afterward TABs |
| TAB0 | No filibuster for TABs |
| TAB1 | Delay after TABs depending on current column position |
| TAB2 | Delay 100 milliseconds subsequently sending TABs |
| TAB3 | Expand TAB characters to spaces |
| BSDLY | Mask for filibuster time needed after BSs |
| BS0 | No filibuster for BSs |
| BS1 | Filibuster l milliseconds after sending BSs |
| VTDLY | Mask for delay time needed after VTs |
| VT0 | No delay for VTs |
| VT1 | Delay 2 seconds later sending VTs |
| FFDLY | Mask for delay time needed after FFs |
| FF0 | No delay for FFs |
| FF1 | Filibuster two seconds subsequently sending FFs |
Choosing Processed Output
Candy output is selected by setting the OPOST option in the c_oflag member:
options.c_oflag |= OPOST;
Of all the different options, you lot will merely probably use the ONLCR option which maps newlines into CR-LF pairs. The rest of the output options are primarily celebrated and date back to the fourth dimension when line printers and terminals could not keep up with the serial data stream!
Choosing Raw Output
Raw output is selected by resetting the OPOST option in the c_oflag fellow member:
options.c_oflag &= ~OPOST;
When the OPOST option is disabled, all other choice $.25 in c_oflag are ignored.
Command Characters
The c_cc grapheme array contains control character definitions as well as timeout parameters. Constants are defined for every element of this array.
| Constant | Description | Primal |
|---|---|---|
| VINTR | Interrupt | CTRL-C |
| VQUIT | Quit | CTRL-Z |
| VERASE | Erase | Backspace (BS) |
| VKILL | Kill-line | CTRL-U |
| VEOF | End-of-file | CTRL-D |
| VEOL | End-of-line | Wagon render (CR) |
| VEOL2 | Second end-of-line | Line feed (LF) |
| VMIN | Minimum number of characters to read | |
| VTIME | Time to look for information (tenths of seconds) |
Setting Software Flow Control Characters
The VSTART and VSTOP elements of the c_cc array contain the characters used for software menstruation control. Normally they should exist set to DC1 (021 octal) and DC3 (023 octal) which represent the ASCII standard XON and XOFF characters.
Setting Read Timeouts
UNIX serial interface drivers provide the ability to specify character and packet timeouts. Ii elements of the c_cc assortment are used for timeouts: VMIN and VTIME. Timeouts are ignored in approved input mode or when the NDELAY option is gear up on the file via open up or fcntl.
VMIN specifies the minimum number of characters to read. If it is set up to 0, then the VTIME value specifies the time to wait for every grapheme read. Notation that this does not mean that a read call for Due north bytes will expect for N characters to come up in. Rather, the timeout will apply to the offset character and the read call will return the number of characters immediately bachelor (upwardly to the number you lot request).
If VMIN is non-zero, VTIME specifies the fourth dimension to expect for the beginning grapheme read. If a grapheme is read within the time given, any read will block (wait) until all VMIN characters are read. That is, once the kickoff graphic symbol is read, the series interface driver expects to receive an entire parcel of characters (VMIN bytes total). If no character is read within the time allowed, then the call to read returns 0. This method allows y'all to tell the series driver you lot need exactly N bytes and whatever read telephone call will render 0 or N bytes. Still, the timeout but applies to the outset character read, so if for some reason the driver misses one grapheme inside the N byte bundle then the read call could cake forever waiting for additional input characters.
VTIME specifies the corporeality of fourth dimension to look for incoming characters in tenths of seconds. If VTIME is set to 0 (the default), reads will cake (wait) indefinitely unless the NDELAY option is gear up on the port with open or fcntl.
Chapter iii, MODEM Communications
This chapter covers the nuts of dialup telephone Modulator/Demodulator (MODEM) communications. Examples are provided for MODEMs that use the defacto standard "AT" control fix.
What Is a MODEM?
MODEMs are devices that modulate series data into frequencies that tin can be transferred over an analog information link such as a telephone line or cablevision Television connection. A standard telephone MODEM converts series information into tones that can be passed over the phone lines; considering of the speed and complexity of the conversion these tones sound more like loud screeching if you listen to them.
Telephone MODEMs are available today that can transfer data across a telephone line at nearly 53,000 bits per second, or 53kbps. In add-on, most MODEMs use information compression technology that can increase the scrap rate to well over 100kbps on some types of data.
Communicating With a MODEM
The first step in communicating with a MODEM is to open and configure the port for raw input:
Listing three - Configuring the port for raw input.
int fd; struct termios options; /* open up the port */ fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY); fcntl(fd, F_SETFL, 0); /* get the current options */ tcgetattr(fd, &options); /* set raw input, ane second timeout */ options.c_cflag |= (CLOCAL | CREAD); options.c_lflag &= ~(ICANON | Echo | ECHOE | ISIG); options.c_oflag &= ~OPOST; options.c_cc[VMIN] = 0; options.c_cc[VTIME] = x; /* set the options */ tcsetattr(fd, TCSANOW, &options); Adjacent you lot need to establish communications with the MODEM. The best fashion to do this is by sending the "AT" command to the MODEM. This also allows smart MODEMs to detect the baud you are using. When the MODEM is continued correctly and powered on information technology volition respond with the response "OK".
List four - Initializing the MODEM.
int /* O - 0 = MODEM ok, -ane = MODEM bad */ init_modem(int fd) /* I - Serial port file */ { char buffer[255]; /* Input buffer */ char *bufptr; /* Current char in buffer */ int nbytes; /* Number of bytes read */ int tries; /* Number of tries so far */ for (tries = 0; tries < iii; tries ++) { /* send an AT control followed past a CR */ if (write(fd, "AT\r", 3) < 3) continue; /* read characters into our cord buffer until we get a CR or NL */ bufptr = buffer; while ((nbytes = read(fd, bufptr, buffer + sizeof(buffer) - bufptr - 1)) > 0) { bufptr += nbytes; if (bufptr[-ane] == '\n' || bufptr[-ane] == '\r') break; } /* nul stop the cord and see if we got an OK response */ *bufptr = '\0'; if (strncmp(buffer, "OK", two) == 0) render (0); } render (-1); } Standard MODEM Commands
Most MODEMs back up the "AT" command ready, so called considering each command starts with the "AT" characters. Each command is sent with the "AT" characters starting in the first column followed by the specific command and a carriage return (CR, 015 octal). Subsequently processing the control the MODEM will reply with i of several textual messages depending on the command.
ATD - Dial A Number
The ATD command dials the specified number. In add-on to numbers and dashes you can specify tone ("T") or pulse ("P") dialing, intermission for one second (","), and wait for a dialtone ("Westward"):
ATDT 555-1212 ATDT 18008008008W1234,1,1234 ATD T555-1212WP1234
The MODEM volition answer with one of the post-obit messages:
NO DIALTONE BUSY NO CARRIER CONNECT CONNECT baud
ATH - Hang Up
The ATH command causes the MODEM to hang up. Since the MODEM must be in "command" mode you probably won't utilise it during a normal phone call.
Near MODEMs volition as well hang upward if DTR is dropped; y'all tin can practise this by setting the baud to 0 for at to the lowest degree ane second. Dropping DTR too returns the MODEM to command way.
Afterwards a successful hang up the MODEM will reply with "NO CARRIER". If the MODEM is withal connected the "CONNECT" or "CONNECT baud" message will be sent.
ATZ - Reset MODEM
The ATZ command resets the MODEM. The MODEM will answer with the cord "OK".Common MODEM Communication Problems
First and foremost, don't forget to disable input echoing. Input echoing volition crusade a feedback loop between the MODEM and calculator.
2nd, when sending MODEM commands you must terminate them with a wagon return (CR) and not a newline (NL). The C character constant for CR is "\r".
Finally, when dealing with a MODEM make certain you use a baud that the MODEM supports. While many MODEMs do auto-baud detection, some have limits (19.2kbps is common) that you must observe.
Chapter iv, Advanced Serial Programming
This chapter covers advanced serial programming techniques using the ioctl(2) and select(2) system calls.
Serial Port IOCTLs
In Chapter 2, Configuring the Serial Port we used the tcgetattr and tcsetattr functions to configure the serial port. Under UNIX these functions utilise the ioctl(2) system call to exercise their magic.
The ioctl system call takes 3 arguments:
int ioctl(int fd, int request, ...);
The fd statement specifies the serial port file descriptor. The request argument is a constant defined in the <termios.h> header file and is typically one of the following:
| Request | Description | POSIX Office |
|---|---|---|
| TCGETS | Gets the current serial port settings. | tcgetattr |
| TCSETS | Sets the serial port settings immediately. | tcsetattr(fd, TCSANOW, &options) |
| TCSETSF | Sets the serial port settings later flushing the input and output buffers. | tcsetattr(fd, TCSANOW, &options) |
| TCSETSW | Sets the serial port settings after allowing the input and output buffers to drain/empty. | tcsetattr(fd, TCSANOW, &options) |
| TCSBRK | Sends a interruption for the given time. | tcsendbreak, tcdrain |
| TCXONC | Controls software flow control. | tcflow |
| TCFLSH | Flushes the input and/or output queue. | tcflush |
| TIOCMGET | Returns the state of the "MODEM" bits. | None |
| TIOCMSET | Sets the country of the "MODEM" bits. | None |
| FIONREAD | Returns the number of bytes in the input buffer. | None |
Getting the Control Signals
The TIOCMGET ioctl gets the current "MODEM" condition bits, which consist of all of the RS-232 indicate lines except RXD and TXD:
| Constant | Clarification |
|---|---|
| TIOCM_LE | DSR (data ready gear up/line enable) |
| TIOCM_DTR | DTR (data last ready) |
| TIOCM_RTS | RTS (request to send) |
| TIOCM_ST | Secondary TXD (transmit) |
| TIOCM_SR | Secondary RXD (receive) |
| TIOCM_CTS | CTS (articulate to ship) |
| TIOCM_CAR | DCD (data carrier find) |
| TIOCM_CD | Synonym for TIOCM_CAR |
| TIOCM_RNG | RNG (band) |
| TIOCM_RI | Synonym for TIOCM_RNG |
| TIOCM_DSR | DSR (data fix ready) |
To get the status bits, telephone call ioctl with a pointer to an integer to agree the bits:
List 5 - Getting the MODEM status bits.
#include <unistd.h> #include <termios.h> int fd; int status; ioctl(fd, TIOCMGET, &condition);
Setting the Command Signals
The TIOCMSET ioctl sets the "MODEM" status $.25 defined above. To drop the DTR signal you can practise:
Listing vi - Dropping DTR with the TIOCMSET ioctl.
#include <unistd.h> #include <termios.h> int fd; int status; ioctl(fd, TIOCMGET, &status); condition &= ~TIOCM_DTR; ioctl(fd, TIOCMSET, status);
The bits that can be set depend on the operating system, commuter, and modes in apply. Consult your operating system documentation for more information.
Getting the Number of Bytes Available
The FIONREAD ioctl gets the number of bytes in the serial port input buffer. As with TIOCMGET y'all pass in a arrow to an integer to agree the number of bytes:
Listing 7 - Getting the number of bytes in the input buffer.
#include <unistd.h> #include <termios.h> int fd; int bytes; ioctl(fd, FIONREAD, &bytes);
This can exist useful when polling a serial port for data, as your program can determine the number of bytes in the input buffer before attempting a read.
Selecting Input from a Serial Port
While simple applications can poll or await on information coming from the serial port, most applications are non simple and need to handle input from multiple sources.
UNIX provides this adequacy through the select(ii) system phone call. This system call allows your program to check for input, output, or error weather on 1 or more file descriptors. The file descriptors can point to serial ports, regular files, other devices, pipes, or sockets. You can poll to check for pending input, wait for input indefinitely, or timeout after a specific amount of fourth dimension, making the select system call extremely flexible.
Most GUI Toolkits provide an interface to select; we volition discuss the Ten Intrinsics ("Xt") library later in this chapter.
The SELECT System Call
The select arrangement call accepts five arguments:
int select(int max_fd, fd_set *input, fd_set *output, fd_set *fault, struct timeval *timeout);
The max_fd argument specifies the highest numbered file descriptor in the input, output, and fault sets. The input, output, and error arguments specify sets of file descriptors for pending input, output, or mistake conditions; specify Naught to disable monitoring for the corresponding condition. These sets are initialized using iii macros:
FD_ZERO(fd_set); FD_SET(fd, fd_set); FD_CLR(fd, fd_set);
The FD_ZERO macro clears the set entirely. The FD_SET and FD_CLR macros add and remove a file descriptor from the set, respectively.
The timeout argument specifies a timeout value which consists of seconds (timeout.tv_sec) and microseconds (timeout.tv_usec ). To poll 1 or more than file descriptors, set the seconds and microseconds to naught. To await indefinitely specify NULL for the timeout pointer.
The select system phone call returns the number of file descriptors that take a pending condition, or -1 if there was an error.
Using the SELECT System Call
Suppose nosotros are reading information from a series port and a socket. We desire to cheque for input from either file descriptor, but want to notify the user if no data is seen within x seconds. To do this we'll demand to use the select system call:
Listing eight - Using SELECT to process input from more than one source.
#include <unistd.h> #include <sys/types.h> #include <sys/time.h> #include <sys/select.h> int due north; int socket; int fd; int max_fd; fd_set input; struct timeval timeout; /* Initialize the input set */ FD_ZERO(input); FD_SET(fd, input); FD_SET(socket, input); max_fd = (socket > fd ? socket : fd) + 1; /* Initialize the timeout structure */ timeout.tv_sec = 10; timeout.tv_usec = 0; /* Practice the select */ n = select(max_fd, Null, NULL, ; /* Meet if there was an error */ if (n 0) perror("select failed"); else if (n == 0) puts("TIMEOUT"); else { /* We have input */ if (FD_ISSET(fd, input)) process_fd(); if (FD_ISSET(socket, input)) process_socket(); } You'll notice that we first bank check the return value of the select system telephone call. Values of 0 and -1 yield the advisable alarm and fault messages. Values greater than 0 mean that we accept information pending on 1 or more file descriptors.
To determine which file descriptor(s) have awaiting input, we use the FD_ISSET macro to test the input set for each file descriptor. If the file descriptor flag is set up then the status exists (input pending in this case) and nosotros need to do something.
Using SELECT with the Ten Intrinsics Library
The 10 Intrinsics library provides an interface to the select system call via the XtAppAddInput(3x) and XtAppRemoveInput(3x) functions:
int XtAppAddInput(XtAppContext context, int fd, int mask, XtInputProc proc, XtPointer information); void XtAppRemoveInput(XtAppContext context, int input);
The select arrangement phone call is used internally to implement timeouts, work procedures, and cheque for input from the X server. These functions can be used with any Xt-based toolkit including Xaw, Lesstif, and Motif.
The proc statement to XtAppAddInput specifies the part to call when the selected condition (eastward.grand. input available) exists on the file descriptor. In the previous case you could specify the process_fd or process_socket functions.
Because Xt limits your access to the select arrangement phone call, you'll need to implement timeouts through another mechanism, probably via XtAppAddTimeout(3x).
Appendix A, Pinouts
This appendix provides pinout information for many of the common serial ports you will observe.
RS-232 Pinouts
RS-232 comes in three flavors (A, B, C) and uses a 25-pin D-Sub connector:
Figure 2 - RS-232 Connector
| Pin | Description | Pin | Description |
|---|---|---|---|
| ane | Globe Ground | 14 | Secondary TXD |
| ii | TXD - Transmitted Data | 15 | Transmit Clock |
| 3 | RXD - Received Information | 16 | Secondary RXD |
| 4 | RTS - Request To Send | 17 | Receiver Clock |
| v | CTS - Clear To Send | 18 | Unassigned |
| six | DSR - Data Set Ready | nineteen | Secondary RTS |
| 7 | GND - Logic Basis | twenty | DTR - Information Terminal Set up |
| 8 | DCD - Data Carrier Detect | 21 | Signal Quality Detect |
| 9 | Reserved | 22 | Ring Discover |
| 10 | Reserved | 23 | Information Rate Select |
| 11 | Unassigned | 24 | Transmit Clock |
| 12 | Secondary DCD | 25 | Unassigned |
| thirteen | Secondary CTS |
RS-422 Pinouts
RS-422 also uses a 25-pin D-Sub connector, only with differential signals:
Figure 3 - RS-422 Connector
| Pivot | Description | Pivot | Description |
|---|---|---|---|
| 1 | Earth Ground | fourteen | TXD+ |
| ii | TXD- - Transmitted Data | 15 | Transmit Clock- |
| three | RXD- - Received Data | 16 | RXD+ |
| 4 | RTS- - Request To Transport | 17 | Receiver Clock- |
| five | CTS- - Clear To Send | eighteen | Unassigned |
| half dozen | DSR - Data Prepare Ready | xix | RTS+ |
| 7 | GND - Logic Ground | xx | DTR- - Data Terminal Gear up |
| viii | DCD- - Data Carrier Discover | 21 | Signal Quality Detect |
| ix | Reserved | 22 | Unassigned |
| 10 | Reserved | 23 | DTR+ |
| xi | Unassigned | 24 | Transmit Clock+ |
| 12 | DCD+ | 25 | Receiver Clock+ |
| xiii | CTS+ |
RS-574 (IBM PC/AT) Pinouts
The RS-574 interface is used exclusively past PC manufacturers and uses a nine-pin male person D-Sub connector:
Figure 4 - RS-574 Connector
| Pin | Description | Pin | Description |
|---|---|---|---|
| 1 | DCD - Data Carrier Detect | 6 | Information Fix Set up |
| ii | RXD - Received Information | 7 | RTS - Request To Send |
| 3 | TXD - Transmitted Data | 8 | CTS - Clear To Send |
| iv | DTR - Data Terminal Set up | 9 | Ring Discover |
| 5 | GND - Logic Ground |
SGI Pinouts
Older SGI equipment uses a nine-pin female person D-Sub connector. Unlike RS-574, the SGI pinouts nigh match those of RS-232:
Figure 5 - SGI nine-Pivot Connector
| Pin | Description | Pin | Clarification |
|---|---|---|---|
| 1 | Globe Ground | six | DSR - Data Set Ready |
| 2 | TXD - Transmitted Information | 7 | GND - Logic Footing |
| 3 | RXD - Received Data | 8 | DCD - Data Carrier Observe |
| 4 | RTS - Request To Send | ix | DTR - Data Terminal Ready |
| 5 | CTS - Clear To Send |
The SGI Indigo, Indigo2, and Indy workstations use the Apple viii-pivot MiniDIN connector for their serial ports:
Figure 6 - SGI viii-Pin Connector
| Pin | Clarification | Pivot | Description |
|---|---|---|---|
| 1 | DTR - Information Last Ready | 5 | RXD - Received Data |
| ii | CTS - Clear To Send | 6 | RTS - Request To Send |
| 3 | TXD - Transmitted Data | 7 | DCD - Data Carrier Discover |
| 4 | GND - Logic Ground | 8 | GND - Logic Ground |
Appendix B, ASCII Control Codes
This chapter lists the ASCII command codes and their names.
Control Codes
The following ASCII characters are used for command purposes:| Proper name | Binary | Octal | Decimal | Hexadecimal |
|---|---|---|---|---|
| NUL | 00000000 | 000 | 0 | 00 |
| SOH | 00000001 | 001 | 1 | 01 |
| STX | 00000010 | 002 | ii | 02 |
| ETX | 00000011 | 003 | iii | 03 |
| EOT | 00000100 | 004 | iv | 04 |
| ENQ | 00000101 | 005 | five | 05 |
| ACK | 00000110 | 006 | 6 | 06 |
| BEL | 00000111 | 007 | 7 | 07 |
| BS | 00001000 | 010 | eight | 08 |
| HT | 00001001 | 011 | ix | 09 |
| NL | 00001010 | 012 | 10 | 0A |
| VT | 00001011 | 013 | xi | 0B |
| NP, FF | 00001100 | 014 | 12 | 0C |
| CR | 00001101 | 015 | 13 | 0D |
| And so | 00001110 | 016 | 14 | 0E |
| SI | 00001111 | 017 | 15 | 0F |
| DLE | 00010000 | 020 | 16 | 10 |
| XON, DC1 | 00010001 | 021 | 17 | xi |
| DC2 | 00010010 | 022 | 18 | 12 |
| XOFF, DC3 | 00010011 | 023 | 19 | 13 |
| DC4 | 00010100 | 024 | twenty | fourteen |
| NAK | 00010101 | 025 | 21 | 15 |
| SYN | 00010110 | 026 | 22 | xvi |
| ETB | 00010111 | 027 | 23 | 17 |
| Can | 00011000 | 030 | 24 | 18 |
| EM | 00011001 | 031 | 25 | xix |
| SUB | 00011010 | 032 | 26 | 1A |
| ESC | 00011011 | 033 | 27 | 1B |
| FS | 00011100 | 034 | 28 | 1C |
| GS | 00011101 | 035 | 29 | 1D |
| RS | 00011110 | 036 | thirty | 1E |
| The states | 00011111 | 037 | 31 | 1F |
Source: https://www.cmrr.umn.edu/~strupp/serial.html
0 Response to "How to Use Serialport Read in C#"
Post a Comment