Understanding Serial Port Configuration in Embedded Development

The serial port is a commonly used interface in computers, with the most common being the RS-232-C interface. It was established in 1970 by the Electronic Industries Alliance (EIA) in collaboration with Bell Systems, modem manufacturers, and computer terminal manufacturers as a standard for serial communication. Its full name is “serial binary data exchange interface technical standard between Data Terminal Equipment (DTE) and Data Communication Equipment (DCE).”

The basic methods of data communication can be divided into parallel communication and serial communication. Parallel communication refers to using multiple data transmission lines to simultaneously transmit all bits of a word of data. Its characteristic is fast transmission speed, suitable for short-distance communication with higher speeds. Serial communication refers to using a single transmission line to sequentially transmit data in bits. Its characteristics include simple communication lines, the ability to use simple cables for communication, reduced costs, and suitability for long-distance communication with slower speeds.

The serial port is a commonly used interface in computers, with the most common being the RS-232-C interface.

Understanding Serial Port Configuration in Embedded Development

Serial port configuration mainly involves setting the members of the struct termios structure.

#include

struct termios

{

unsigned short c_iflag; /* Input mode flags */

unsigned short c_oflag; /* Output mode flags */

unsigned short c_cflag; /* Control mode flags*/

unsigned short c_lflag; /* Local mode flags */

unsigned char c_line; /* Line discipline */

unsigned char c_cc[NCC]; /* Control characters */

speed_t c_ispeed; /* Input speed */

speed_t c_ospeed; /* Output speed */

};

}

To save the original serial port settings

For safety and ease of debugging later, the original serial port configuration can be saved using the function tcgetattr(fd, &old_cfg). This function retrieves the configuration parameters of the terminal pointed to by fd and stores them in the termios structure variable old_cfg. This function can also test whether the configuration is correct and whether the serial port is available. If the call is successful, the return value of the function is 0, and if it fails, the return value is -1. Example:

if (tcgetattr(fd, &old_cfg) != 0)

{

perror(“tcgetattr”);

return -1;

}

}

To activate options CLOCAL and CREAD, which are used for local connection and receive enable respectively, these two options must first be activated using bitwise masking.

newtio.c_cflag |= CLOCAL | CREAD;

}

Calling the cfmakeraw() function sets the terminal to raw mode, and in the following examples, raw mode is used for serial data communication.

cfmakeraw(&new_cfg);

}

Setting the baud rate } The baud rate can be set using specific functions; users cannot directly manipulate it using bitwise masking. The main functions for setting the baud rate are: cfsetispeed() and cfsetospeed(). }Example:

cfsetispeed(&new_cfg, B115200);

cfsetospeed(&new_cfg, B115200);

}Setting character size } Unlike setting the baud rate, there are no readily available functions for setting character size; bitwise masking is required. Generally, the bit mask in the data bits is first cleared, and then reset as required }Example:

new_cfg.c_cflag &= ~CSIZE; /* Clear the data bit mask */

new_cfg.c_cflag |= CS8;

}Setting parity bit } Setting the parity bit requires using two members in termios: c_cflag and c_iflag. First, the parity enable flag PARENB in c_cflag must be activated, and whether to perform parity. This will add a parity bit to the output data and check the input data for parity. Additionally, the parity enable for input data in c_iflag must also be activated (INPCK).}Example:}Odd parity

new_cfg.c_cflag |= (PARODD | PARENB);

new_cfg.c_iflag |= INPCK;

}Even parity

new_cfg.c_cflag |= PARENB;

new_cfg.c_cflag &= ~PARODD;

new_cfg.c_iflag |= INPCK;

}Setting stop bits } Setting stop bits is achieved by activating CSTOPB in c_cflag. If the stop bit is one, clear CSTOPB, and if it is two, activate CSTOPB. }Example:

new_cfg.c_cflag &= ~CSTOPB; /* Set stop bit to one bit */

new_cfg.c_cflag |= CSTOPB; /* Set stop bit to two bits */

}Setting minimum characters and wait time } In the absence of specific requirements for receiving characters and wait time, these can be set to 0, meaning that the read() function will return immediately in any case, and the serial port operation will be set to non-blocking mode. }Example:

new_cfg.c_cc[VTIME] = 0;

new_cfg.c_cc[VMIN] = 0;

}Clearing the serial port buffer } After resetting the serial port, appropriate handling of the current serial device is required. The functions declared in tcdrain(), tcflow(), tcflush(), etc., can be called to handle the data currently in the serial port buffer. }Prototype:

int tcflush(int fd, int queue_selector); /* Used to clear input/output buffer*/

} The tcflush() function handles data that has not been transmitted in the buffer or data received but not yet read. The handling method depends on the value of queue_selector, which can take the following values.

· TCIFLUSH:Clears data received but not yet read.

· TCOFLUSH:Clears output data that has not been successfully transmitted.

· TCIOFLUSH:Includes the functions of the previous two, clearing both unprocessed input and output data.

}Example:tcflush(fd, TCIFLUSH);

}Activating configuration } After completing all serial port configurations, the newly configured settings must be activated. The function used for this is tcsetattr(), with the function prototype: }tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

The parameter termios_p is the new configuration variable of type termios.

The parameter optional_actions can take the following three values:

· TCSANOW:Modifications take effect immediately.

· TCSADRAIN:Modifications take effect after all output written to fd has been transmitted.

· TCSAFLUSH:All accepted but unread input will be discarded before modifications take effect.

If the function call is successful, it returns 0, and if it fails, it returns -1. The code is as follows:

Open the serial port using the open function to open the serial port } Read and write to the serial port } Use the read/write functions to read and write to the serial port.

Opening files: There are three standard functions to open files: fopen(), fdopen(), and freopen(). They can open in different modes but all return a pointer to FILE, which points to the corresponding I/O stream.

Leave a Comment