Linux serial programming Chinese English Simplified Control C

xiaoxiao2021-03-06  14

2.3. Input Concepts for Serial Devices Enterging Concepts of Serial Pit Equipment Here Three Different Input Concepts Will Be Presented. The appropriate Concept

Has to be chosen for the intended Application. WHENEVER POSSIBLE, DO NOT loop Reading

Single Characters to Get a Complete String. When I Did this, I Lost Characters,

WHEREAS A Read for The Whole string Did Not show any.

Here will introduce three different input methods of serial devices, you need to choose the right way for your program. Any

In the case of possible, do not use loop read single characters to get a string. When I did this, I just

Lost characters, and read the Read method of the entire string, there is no such error.

2.3.1. Canonical Input Processing Standard Input Mode This Is The Normal Processing Mode for Terminals, But Can Also BE Useful for Communicating

WITHER DL INPUT IS Processed in Units of Lines, Which Means That A Read Will

ONLY RETURN A FULL LINE OF INPUT. A line is by default terminated by a nl (ASCII

LF), an end of file, or an end of line character. A Cr (The Dos / Windows Default

End-of-line) Will NOT TERMINATE A LINE with the default settings.

Canonical Input Processing Can Also Handle The Erase, Delete Word, And Reprint

Characters, Translate Cr To NL, ETC ..

This is the standard processing mode of the terminal device, which is also useful in the input communication with other DLs. This party

In the formula, the READ will return to a full line of complete input. The end of the one-line, the default is NL (ASCII value LF), file knot

Brass, or a row end character. In the default setting, Cr (the default line end in DOS / Windows is not

Row end sign.

Standard input processing can also handle clear, delete words, redraw characters, conversion CRs NL, and the like.

2.3.2. Non-Canonical Input Processing Non-standard Input Patterns Non-Canonical Input Processing Will Handle A Fixed Amount of Characters Per Read,

And Allows for a Character Timer. This Mode SHOULD BE Used if your application

Always Read a fixed number of character of character of characters, or if the connection device sends burs

Of character.

Non-standard input processing can be used to read the fixed quantity character each time and allow the use of characters to receive time

Timer. This mode can be used in a program that reads a fixed length string, or the connected device will suddenly send

In the case of a large number of characters.

2.3.3. Asynchronous Input asynchronous input mode The Two modes described Above Can Be buy in synchronous and askRONM MODE.SYNCHRONONKED, WHERE A Read Statement Will Block, UnTil The Read IS

Satisfied. in Asynchronous Mode The Read Statement Will Return Immediatly and Send

A Signal To The Calling Program Upon Completion. This Signal Can Be Received By

A Signal Handler.

The two modes described above can be used in synchronous and asynchronous transmission modes. The default is working in synchronous mode, too

The status of the READ will be blocked (Block) before the data is not read. And in asynchronous mode, the state of the READ

A signal to the called program will be returned immediately and send a signal to the call until work. This signal can be received by the signal processing program handler.

2.3.4. Waiting for Input from Multiple Sources Waiting for Input from Multi-Source This Is Not A Different Input Mode, But Might Be Useful, IF you are handling multiple

Devices. in My Application I WAS Handling Input over A TCP / IP Socket and Input over

A Serial Connection from another computer quasi-simultaneously. The Program EXAMPLE

Given Below Will Wait for Input from Two Different Input Sources. If INPUT from ONE

Source Becomes Available, IT Will Be Processed, And The Program Will Then Wait for

NEW INPUT.

The Approach Presented Below Seem Rather Complex, But it is important to keep in

Mind That Linux Is a Multi-Processing Operating System. The SELECT SYSTEM CALL WILL

NOT LOAD THE CPU While Waiting for Input, Whereas Looping Until Input Becomes

Available Would Slow Down Other Processes Executing At The Same Time.

This section is not another input mode, but if you want to handle data from multiple devices, it may be very

use. In my application, I need to handle other calculations at the same time through a TCP / IP socket and a serial port.

Enter from the machine. The sample program given below will wait for input from two different input sources. If one of the signals

The source appears, the program will be handled accordingly, and the program will continue to wait for new inputs.

The method raised later seems quite mix, but remember that Linux is a multi-process operating system. System call

SELECT does not increase the burden of the CPU when waiting for the input signal, and if the polling method is used to wait for the input signal

If you will slow down other processes that are being executed.

3. Program Examples Sample Program All Examples Have Been Derived from Miniterm.c. The Type Ahead Buffer IS Limitedto 255 Characters, Just Like The Maximum String Length for Canonical Input Processing

( Or ).

SEE the Comments in the code for expent ion of the use of the defvent input.

I hope what the code is understandable. The Example for Canonical Input is comments

BEST, THE OTHER EXAMPLES Are Comment Only Where The Difer from The Example for

CANONICAL INPUT TO EMPHASIZE The DIFFERENCES.

The Descriptions Are Not Complete, But You Are Encouraged To Experiment with The

Examples to Derive The Best Solution for your application.

Don't forget to give the appropriate Serial ports the right permissions (e. G .:

CHMOD A RW / DEV / TTYS1)!

All examples come from Miniterm.c. The Type Ahead buffer is limited to the size of 255 bytes, this with the standard

The string of the Canonical Input process is the maximum length of the same length ( or ).

Note in the code explains the use of different input modes to hopes that these codes can be easily understood. Standard input program

Examples have made the most detailed annotations, and other examples have been emphasized in places that differ from standard input examples.

The narrative is not very complete, but you can motivate you to do experiments to this example to delay the best solution to the application you need.

Don't forget to give the serial port correct permissions (that is, CHMOD A RW / dev / TTYS1)!

3.1. Canonical Input Processing Standard Input Mode

Code

#include

#include

#include

#include

#include

/ * baudrate settings area defined in , which is includD by * /

// baud rate setting is defined in . Is included in

#define baudrate b38400

/ * Change this definition for the correct port * /

/ / Define the serial number you need

#define modemdevice "/ dev / ttys1"

#define _posix_source 1 / * POSIX Compliant Source POSIX system compatible * /

#define false 0

#define True 1

Volatile Int Stop = FALSE;

MAIN () {

INT FD, C, RES;

Struct Termios Oldtio, NewTIO;

Char BUF [255];

/ * Open modem device forreading and write and not as controlling

Tty Because We don't want to get killed if linenoise senends ctrl-c.

Turn on the device for reading and writing, but do not control TTY mode, because we don't want to send Ctrl-C

After the end of this process

* /

FD = Open (ModemDevice, o_rdwr | o_nock ";

IF (fd <0) {PERROR (MODEMDEVICE); EXIT (-1);

Tcgetattr (fd, & oldtio); / * Save Current Serial Port Settings * /

// Store the current serial settings

Bzero (& NewTIO, SIZEOF (NewTIO)); / * Clear Struct for New Port Settings * /

/ / Empty new serial port set structure

/ *

Baudrate: Set BPS Rate. You Could Also Use Cfsetispeed and cfsetospeed.

Crtscts: Output Hardware Flow Control (ONLY USED IF The Cable Has All

Ecessary Lines. See SECT. 7 of Serial-HOWTO

CS8: 8N1 ​​(8bit, No Parity, 1 STOPbit)

Clocal: Local Connection, No Modem Contol

CREAD: Enable Receiving Characters

BaudRate: Set the transfer rate BPS of the serial port, you can also use cfsetispeed and cfsetospeed to set

CRTSCTS: Output hardware flow control (only work under the cable with complete lines, refer to Serial-Howto Section 7)

CS8: 8N1 ​​(8-bit data for each frame, no parity check, 1 bit stop bit)

CLOCAL: Local connection, no modem control

CREAD: Allows receiving data

* /

NEWTIO.C_CFLAG = Baudrate | CRTSCTS | CS8 | CLOCAL | CREAD

/ *

Ignpar: Ignore bytes with Parity Errors

ICRNL: Map Cr to NL (OtherWise A Cr Input On The Other Computer Will Not NOT

Terminate Input) OtherWise Make Device Raw (No Other Input Processing)

Ignpar: Ignore parity error

ICRNL: Take the CR image into NL (otherwise the CR from other machines cannot terminate) or set the device

For the RAW status (no additional input processing)

* /

NEWTIO.C_IFLAG = IGNPAR | ICRNL;

/ *

Raw Output. Raw mode output

* /

NEWTIO.C_OFLAG = 0;

/ *

Icanon: Enable Canonical Input

Disable All echo functionality, and don't send signals to calling program

ICANON: Start the standard output, close all ECHO functions, send signals to the program

* /

NEWTIO.C_LFLAG = ICANON;

/ *

Initialize All Control Characters

Default Values ​​Can Be Found in /usr/include/termios.h, and

Are Given in The Comments, But We Don't Need Them Here

Initialize all control characters, the default value can be found in /usr/include/termios.h,

And have an annotation, but here we don't need to consider these

* /

NEWTIO.C_CC [VINTR] = 0; / * CTRL-C * /

NEWTIO.C_CC [Vquit] = 0; / * Ctrl- / * /

NEWTIO.C_CC [VERASE] = 0; / * DEL * /

NEWTIO.C_CC [vkill] = 0; / * @ * /

NEWTIO.C_CC [veof] = 4; / * ctrl-d * /

NEWTIO.C_CC [VTIME] = 0; / * Inter-character Timer Unused * /

/ * Do not use timers in characters * /

NEWTIO.C_CC [VMIN] = 1; / * blocking read untric 1 character arrives * /

/ * Block until reading a character * /

NEWTIO.C_CC [VSWTC] = 0; / * '/ 0' * /

NEWTIO.C_CC [VStart] = 0; / * Ctrl-q * /

NEWTIO.C_CC [vStop] = 0; / * Ctrl-S * /

NEWTIO.C_CC [VSUSP] = 0; / * Ctrl-z * /

NEWTIO.C_CC [VEOL] = 0; / * '/ 0' * /

NEWTIO.C_CC [Vreprint] = 0; / * CTRL-R * /

NEWTIO.C_CC [VDISCARD] = 0; / * CTRL-U * /

NEWTIO.C_CC [Vwerase] = 0; / * Ctrl-w * /

NEWTIO.C_CC [VLNEXT] = 0; / * Ctrl-V * /

NEWTIO.C_CC [veol2] = 0; / * '/ 0' * /

/ *

Now clean the modem line and activate the settings for the port

Clear the data cable, start a new serial setting

* /

TCFlush (FD, TCIFLUSH);

TcSetattr (FD, Tcsanow, & NewTIO);

/ *

Terminal Settings Done, Now Handle Input

In this Example, Inputting A 'Z' At the beginning of a line Will

EXIT The Program.

The terminal setting is complete, and the data can now be handled.

In this program, enter a 'Z' in a row, will terminate the program.

* /

While (stop == false) {/ * loop untric we have a Terminating condition * /

/ / Circulation until the termination conditions are met

/ * Read Blocks Program Execution Until a line Terminating Character IS

Input, Even IF More Than 255 Chars Are Input. if The Numberof Characters Read Is Smaller Than The Number of Chars Available,

Subsequent Reads Will Return The Remaining Chars. Res Will Be Set

To The Actual Number of Characters Actually Read

Even if you enter more than 255 bytes, the segment read segment will still be stopped until the end of the end.

If the read characters are less than the number of characters that should be obtained, the remaining character is read at the next reading.

RES is used to get the number of bytes that really read each time

* /

Res = Read (FD, BUF, 255);

BUF [RES] = 0; / * SET End of String, So We can Printf * /

// Set the string end of the string, so that printf can be used smoothly

Printf (":% S:% D / N", BUF, RES);

IF (Buf [0] == 'Z') stop = true;

}

/ * Restore the old port set settings Restore old serial settings * /

TcSetattr (fd, tcsanow, & oldtio);

}

3.2. Non-Canonical Input Processing Non-standard Input Patterns in non-canonical Input Processing Mode, Input Is Not Assembled INTO LINES AND INPUT

Excessing (Erase, Kill, Delete, etc.) Does Not Occur. Two Parameters Control There

Behavior of this mode: c_cc [vTIME] sets the character timer, and c_cc [vmin] sets

The minimum number of character of character satisfying the read.

IF

MIN> 0 and time = 0, min sets the number of character of character of characters to receive before

The read is satisfied. as time is zero, The Timer is not used.

IF

Min = 0 and Time> 0, Time Serves as a timeout value. The read will be

Satisfied if A Single Character is Read, or Time is Exceeded (t = time * 0.1 s).

IF Time Is Exceeded, No Character Will Be Returned.

IF

MIN> 0 and Time> 0, Time Serves as an inter-character timer. The Read

Will Be Satisfied if min character receifled, or the time between two characters

Exceeds Time. The Timer Is Restarted Every Time a Character Is Received and ONLY

Becomes Active After The First Character Has Been Received.

IF

MIN = 0 and time = 0, read will be satisfied immediately. The number ofcharacters currently available, or the number of characters Requested Will Be Returned.

According to Antonino (See Contributions), You Could Issue A FCNTL (FD, F_SETFL, FNDELAY);

BEFORE Reading to Get The Same Result.

By modifying newtio.c_cc [vTIME] and newtio.c_cc [vmin] all model described Above can be tsted.

In non-standard input mode, the input data is not combined, and ERASE, KILL, DELETE, etc.

Incorporation. We just use two parameters to control the input behavior of this mode: c_cc [vTIME] sets the character input

The timer of the separation time, and the c_cc [vmin] sets the minimum number of bytes that satisfy the read function.

MIN> 0, Time = 0: The read function returns after reading the number of characters that read the MIN value.

Min = 0, Time> 0: Time determines the timeout value, the read function is reading a character, or waiting for reading

Take the time over Time (t = time * 0.1s) back, that is, even if you don't read the number from the serial port

According to the reading function, it will return after the Time time.

Min> 0, Time> 0: After reading the data of the Min byte, the read function is confiscated by the TIME time

Returns it to the data. This timer will retrieve the first byte while receiving the first byte while receiving the first byte while receiving the first byte.

start up.

MIN = 0, Time = 0: The read function will return immediately. The number of characters that actually read, or the characters to be read

The number will be returned as the return value. According to Antonino, FCNTL (FD, F_SETFL,

Fndelay, get the same result before reading.

Change Nettio.c_cc [vtime] and newTIO.C_CC [VMIN] can test the above settings.

Code

#include

#include

#include

#include

#include

#define baudrate b38400

#define modemdevice "/ dev / ttys1"

#define _posix_source 1 / * POSIX Compliant Source * /

#define false 0

#define True 1

Volatile Int Stop = FALSE;

MAIN () {

INT FD, C, RES;

Struct Termios Oldtio, NewTIO;

Char BUF [255];

FD = Open (ModemDevice, o_rdwr | o_nock ";

IF (fd <0) {PERROR (MODEMDEVICE); EXIT (-1);

Tcgetattr (FD, & Oldtio); / * Save Current Port Settings * /

Bzero (& NewTIO); NewTIO.C_CFLAG = Baudrate | CRTSCTS | CS8 | CLOCAL | CREAD

NEWTIO.C_IFLAG = IGNPAR;

NEWTIO.C_OFLAG = 0;

/ * SET INPUT MODE (Non-Canonical, No Echo, ...) * /

// Setting the input mode is non-standard input

NEWTIO.C_LFLAG = 0;

NEWTIO.C_CC [VTIME] = 0; / * Inter-character Timer Unused * /

/ / Not using a character interval timer

NEWTIO.C_CC [VMIN] = 5; / * blocking read unientil 5 chars received * /

// After receiving the number of 5 characters, the read function returns

TCFlush (FD, TCIFLUSH);

TcSetattr (FD, Tcsanow, & NewTIO);

While (stop == false) {/ * loop for input * /

Res = read (FD, Buf, 255); / * Returns After 5 Chars Have Been Input * /

BUF [RES] = 0; / * SO We can printf ... * /

Printf (":% S:% D / N", BUF, RES);

IF (Buf [0] == 'Z') stop = true;

}

TcSetattr (fd, tcsanow, & oldtio);

3.3. Asynchronous INPUT asynchronous input mode

Code

#include

#include

#include

#include

#include

#include

#define baudrate b38400

#define modemdevice "/ dev / ttys1"

#define _posix_source 1 / * POSIX Compliant Source * /

#define false 0

#define True 1

Volatile Int Stop = FALSE;

Void signal_handler_io (int stat); / * definition of signal handler * /

/ / Define the signal handler

INT WAIT_FLAG = true; / * True While No Signal Received * /

// True represents no signal, waiting for

MAIN () {

INT FD, C, RES;

Struct Termios Oldtio, NewTIO;

Struct SigAction Saio;

/ * Definition of signal action * /

/ / Define the structure of the signal processing

Char BUF [255];

/ * Open the device to be non-blocking (read will return immediatly) * /

// Yes to open the device read function immediately with a non-blocking mode, it will not block

FD = Open (ModemDevice, O_RDWR | O_NOCTTY | O_NONBLOCK);

IF (fd <0) {PERROR (MODEMDEVICE); EXIT (-1);} / * Install the device isynchronous * /

/ / Install the signal handler before performing an apparatus asynchronous transmission

Saio.sa_handler = signal_handler_io;

SAIO.SA_MASK = 0;

SAIO.SA_FLAGS = 0;

Saio.sa_restorer = NULL;

Sigction (SIGIO, & SAIO, NULL);

/ * ALLOW the process to receive sigio * /

// Allow the process to receive SIGIO signal

FCNTL (FD, F_SETOWN, GETPID ());

/ * Make The File Descriptor asynchronous (The Manual Page Says Only

O_Append and o_nonblock, Will Work with f_setfl ... * /

/ / Set the file descriptor of the serial port as an asynchronous, and the Man said, only o_append and o_nonblock can use f_setfl

FCNTL (FD, F_SETFL, FASYNC);

Tcgetattr (FD, & Oldtio); / * Save Current Port Settings * /

/ * SET New Port Settings for Canonical Input Processing * /

/ / Set new serial port for standard input mode

NEWTIO.C_CFLAG = Baudrate | CRTSCTS | CS8 | CLOCAL | CREAD

NEWTIO.C_IFLAG = IGNPAR | ICRNL;

NEWTIO.C_OFLAG = 0;

NEWTIO.C_LFLAG = ICANON;

NEWTIO.C_CC [VMIN] = 1;

NEWTIO.C_CC [VTIME] = 0;

TCFlush (FD, TCIFLUSH);

TcSetattr (FD, Tcsanow, & NewTIO);

/ * loop while waiting for infut. Normally We 10 Do Something

Useful Here loops Wait for input, usually we will do other things here * /

While (stop == false) {

Printf ("./ n"); USLEP (100000);

/ * after receiving sigio, wait_flag = false, input is availableand can be ready * /

// After receiving the SIGIO signal, wait_flag = false, indicating that there is input, and can read it.

IF (wait_flag == false) {

Res = Read (FD, BUF, 255);

BUF [RES] = 0;

Printf (":% S:% D / N", BUF, RES);

IF (res == 1) stop = true; / * stop loop if only a cr at * /

WAIT_FLAG = true; / * Wait for new input Wait a new input * /

}

}

/ * Restore Old Port Settings * /

TcSetattr (fd, tcsanow, & oldtio);

}

/ ************************************************** ************************** SIGNAL HANDLER. SETS WAIT_FLAG to FALSE, TO INDICATE ABOVE LOOP THAT *

* CHARACTERS HAVE BEEN Received. *

*********************************************************** ************************ /

// Signal processing function, set wait_flag to false to tell the above loop function serial port to receive characters

void signal_handler_io (int status) {

Printf ("Received Sigio Signal./N");

WAIT_FLAG = FALSE;

}

3.4. Waiting for Input from Multiple Sources Waiting for the input of multiple sources This section section Kept to be a minimum. It is just intended to be a hint, and thereforefore

The Example Code Is Kept Short. This Will Not Only Work with Serial Ports, But with

Any Set of File Descriptors.

The SELECT CALL AND Accompanying Macros Use a fd_set. This is a bit array, which

HAS A Bit Entry for Every Valid File Descriptor Number. SELECT WILL Accept A fd_set

WITH THE BITS SET for the Relevant File Descriptors and Returns A fd_set, in which

The Bits for the File Descriptors Are Set Where Input, Output, or An Exception

Occurred. All Handling of Fd_set is Done with the provided macros. See Also The PROX

Manual Page SELECT (2).

This part is very little content, just as a prompt, so this code is also very short. And this part of the content is not only suitable

For serial port programming, and suitable for any set of file descriptors.

SELECT calls and their corresponding macros, using fd_set. This is a bit array, where each bit represents one

Effective file description symbol. SELECT calls to receive a valid file descriptor structure and return FD_SET bit

Array, if a bit is set to 1 in this bit array, it means that the corresponding file descriptor has an input, output or

There are exceptions. All fg_set's processing is provided by macros, and the specific reference is Man SELECT 2.

Code

#include

#include

#include

Main ()

{

INT FD1, FD2; / * Input Sources 1 and 2 Input Source 1 and 2 * /

FD_SET READFS; / * File Descriptor set * /

INT MAXFD; / * Maximum file desciptor Used the maximum value of file descriptor * / int loop = 1; / * loop while true cycle logo * /

/ * Open_INPUT_SOURCE OPENS A Device, Sets The Port Correctly, And

Returns A File Descriptor * /

// Open_INPUT_SOURCE function Open a device, set the port correctly, and return to the file descriptor

FD1 = OPEN_INPUT_SOURCE ("/ dev / ttys1"); / * COM2 * /

IF (fd1 <0) exit (0);

FD2 = OPEN_INPUT_SOURCE ("/ dev / ttys2"); / * COM3 * /

IF (fd2 <0) exit (0);

Maxfd = max (FD1, FD2) 1; / * Maximum Bit Entry (fd) to Test * /

/ * loop for input * /

While (loop) {

FD_SET (FD1, & ReadFS); / * SET TESTING Forum 1 * /

FD_SET (FD2, & Readfs); / * set testing for source 2 * /

/ * block unient INPUT BECOMES AVAILABLE blocks until you have entered * /

SELECT (MAXFD, & ReadFS, NULL, NULL, NULL);

IF (fd_isset (fd1)) / * Input from Source 1 Available Source 1 has input * /

Handle_INPUT_FROM_SOURCE1 ();

IF (fd_isset (fd2)) / * Input from Source 2 Available Source 2 has input * /

Handle_INPUT_FROM_SOURCE2 ();

}

}

The Given Example Blocks Indefinitely, Until Input from One of the Sources Becomes Available. If You Need To Timeout on Input, Just Replace The SELECT CALL BY:

This example can cause unknown blocking, knowing one of the sources of data input. If you need to set a timeout value for the input, use the following SELECT:

Code

Int res;

Struct TimeVal Timeout;

/ * Set Timeout Value With Input Loop Sets the timeout value in the input loop * /

Timeout.tv_usec = 0; / * MilliseConds Sets milliseconds * /

Timeout.tv_sec = 1; / * Seconds Settings the number of seconds * /

Res = SELECT (MAXFD, & Readfs, Null, Null, & Timeout);

IF (res == 0)

/ * Number of file descriptors with input = 0, timeout accurred. All file descriptors are not entered, timeout exits returns 0 * /

This example will timeout after 1 second. If a timeout occurs, select will return 0, but beware that Timeout is decremented by the time actually waited for input by select. If the timeout value is zero, select will return immediatly. This example will After 1 second, I will exit. If timeout occurs, select returns 0, please note that timeout is decremented by the time according to the actual waiting input, if Timeout is set to 0, the SELECT function will immediately exit.

转载请注明原文地址:https://www.9cbs.com/read-47847.html

New Post(0)