Linux 下使用rs232
时间:2005-03-18 来源:icestare
Serial Programming Guide for POSIX Operating Systems
5th Edition
Michael R. Sweet
Copyright 1994-1999, All Rights Reserved.
Serial Port Files
Each serial port on a UNIX system has one or more device files (files in the /dev directory) associated with it:
Table 2 - Serial Port Device Files |
||
System |
Port 1 |
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 |
Open Options
You'll notice that when we opened the device file we used two other flags along with the read+write mode:
fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);
The O_NOCTTY flag tells UNIX that this program doesn't want to be the "controlling terminal" for that port. If you don't specify this then any input (such as keyboard abort signals and so forth) will affect your process. Programs like getty(1M/8) use this feature when starting the login process, but normally a user program does not want this behavior.
The O_NDELAY flag tells UNIX that this program doesn't care what state the DCD signal line is in - whether the other end of the port is up and running. If you do not specify this flag, your process will be put to sleep until the DCD signal line is the space voltage.
Writing Data to the Port
Writing data to the port is easy - just use the write(2) system call to send data it:
n = write(fd, "ATZ ", 4);
if (n < 0)
fputs("write() of 4 bytes failed! ", stderr);
The write function returns the number of bytes sent or -1 if an error occurred. Usually the only error you'll run into is EIO when a MODEM or data link drops the Data Carrier Detect (DCD) line. This condition will persist until you close the port.
Reading Data from the Port
Reading data from a port is a little trickier. When you operate the port in raw data mode, each read(2) system call will return however many characters are actually available in the serial input buffers. If no characters are available, the call will block (wait) until characters come in, an interval timer expires, or an error occurs. The read function 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 available on the port. To restore normal (blocking) behavior, call fcntl() without the FNDELAY option:
fcntl(fd, F_SETFL, 0);
This is also used after opening a serial port with the O_NDELAY option.
Closing a Serial Port
To close the serial port, just use the close system call:
close(fd);
Closing a serial port will also usually set the DTR signal low which causes most MODEMs to hang up.
Chapter 2, Configuring the Serial Port
This chapter discusses how to configure a serial port from C using the POSIX termios interface.
The POSIX Terminal Interface
Most systems support the POSIX terminal (serial) interface for changing parameters such as baud rate, character size, and so on. The first thing you need to do is include the file <termios.h>; this defines the terminal control structure as well as the POSIX control functions.
The two most important POSIX functions are tcgetattr(3) and tcsetattr(3). These get and set terminal attributes, respectively; you provide a pointer to a termios structure that contains all of the serial options available:
Table 3 - Termios Structure Members |
|
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 rate, number of data bits, parity, stop bits, and hardware flow control. There are constants for all of the supported configurations.
Table 4 - Constants for the c_cflag Member |
|
Constant |
Description |
CBAUD |
Bit mask for baud rate |
B0 |
0 baud (drop 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 data bits |
CS8 |
8 data bits |
CSTOPB |
2 stop bits (1 otherwise) |
CREAD |
Enable receiver |
PARENB |
Enable parity bit |
PARODD |
Use odd parity instead of even |
HUPCL |
Hangup (drop DTR) on last close |
CLOCAL |
Local line - do not change "owner" of port |
LOBLK |
Block job control output |
CNEW_RTSCTS |
Enable hardware flow control (not supported on all platforms) |
The c_cflag member contains two options that should always be enabled, CLOCAL and CREAD. These will ensure that your program does not become the 'owner' of the port subject to sporatic job control and hangup signals, and also that the serial interface driver 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. See the next section for information on the POSIX functions used to set the baud rate.
Never initialize the c_cflag (or any other flag) member directly; you should always use 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 you from clobbering a bit flag that is needed in a newer serial driver.
Setting the Baud Rate
The baud rate is stored in different places depending on the operating system. Older interfaces store the baud rate in the c_cflag member using one 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(3) functions are provided to set the baud rate in the termios structure regardless of the underlying operating system interface. Typically you'd use the following code to set the baud rate:
Listing 2 - Setting the baud rate.
struct termios options;
/*
* Get the current options for the port...
*/
tcgetattr(fd, &options);
/*
* Set 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(3) function fills the termios structure you provide with the 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. There are other constants to wait for input and output to finish or to flush the input and output buffers.
Most systems do not support different input and output speeds, so be sure to set both to the same value for maximum portability.
Table 5 - Constants for tcsetattr |
|
Constant |
Description |
TCSANOW |
Make changes now without waiting for data to complete |
TCSADRAIN |
Wait until everything has been transmitted |
TCSAFLUSH |
Flush input and output buffers and make the change |
Setting the Character Size
Unlike the baud rate, there is no convienience function to set the character size. Instead you must do a little bitmasking to set things up. The character size is specified in bits:
options.c_cflag &= ~CSIZ