About embedded Linux serial port programming of AM335x AM62x
The serial port devices under Linux are mainly in the dev directory, such as ttySx or ttySUx or ttyOx. For example, am1808 is ttyS0-S2 SU0-SU7, and am335x is ttyO0-O5.
1. This basic programming API introduction, the most basic serial port settings include baud rate settings, parity bit and stop bit settings.
1.1 The setting of the serial port mainly involves setting the member values of the struct termios structure.
struct termios
{
unsigned short c_iflag; /* Input mode flag */
unsigned short c_oflag; /* Output mode flag */
unsigned short c_cflag; /* Control mode flag */
unsigned short c_lflag; /* Local mode flag */
unsigned char c_line; /* Control protocol */
unsigned char c_cc[NCC]; /* Control mode character */
};
All operations on the serial port are implemented through the structure struct termios and several functions. The two most commonly used functions are tcgetattr() and tcsetattr(). In almost all cases, the program obtains the current settings of the device through the tcgetattr() function, then modifies these settings, and finally uses tcsetattr() to make these settings effective. Many programs will save the initial terminal settings and restore them before terminating.
The function returns 0 to indicate success.
1.2 tcgetattr and tcsetattr functions
int tcgetattr (int fd ,struct termios *t)
Used to obtain the current setting value of the device represented by the file descriptor fd and write it into pointer t
int tcsetattr (int fd, int options ,struct termios *t)
Used to assign the setting value in the termios structure pointer t to the device terminal currently represented by the file descriptor fd
The options parameter determines when the change takes effect.
TCSANOW——Modification takes effect immediately
TCSADRAIN——All sent outputs take effect after being written to fd
TCSAFLUSH——Take effect when the output queue is empty
For example: Here is the code to change the baud rate:
struct termios Opt;
tcgetattr(fd, &Opt);
cfsetispeed(&Opt,B19200); /*设置为19200Bps*/ cfsetospeed(&Opt,B19200);
tcsetattr(fd,TCANOW,&Opt);
1.3 Baud rate setting
The cfsetispeed() and cfsetospeed() functions are used to set the input and output speeds of the device respectively.
int cfsetispeed(struct termios *t ,speed_t speed)
int cfsetospeed(struct termios *t ,speed_t speed)
The input and output speeds of the device are set to speed through the structure t. They only set the speed of the termios structure. If you want to modify the speed of the device, you need to call the tcsetattr() function. Let's take a look at an example of setting the baud rate:
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
int i; int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd1, TCSANOW, &Opt);
if (status != 0)
{
perror("tcsetattr fd1");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
}
1.4 tcflush() function
Used to discard some data on the device. The discarded data depends on the second parameter queue_selector
The prototype is: int tcflush (int fd, int queue_selector)
TCIFLUSH - discards all data that has been received on the interface but not read in
TCOFLUSH - discards all data that has been written to the interface but not sent
TCIOFLUSH - discards all data that has not been read or sent on the input and output queues
1.5 Parity and stop bit settings
No parity (8N1):
options.c_cflag &= ~PARENB; //No parity
options.c_cflag &= ~CSTOPB; //1 stop bit
options.c_cflag &= ~CSIZE; //No bit mask
options.c_cflag |= CS8; //8 data bits
Even parity (7E1):
options.c_cflag |= PARENB; //with parity
options.c_cflag &= ~PARODD; //even parity
options.c_cflag &= ~CSTOPB; //one stop bit
options.c_cflag &= ~CSIZE; //no bit mask
options.c_cflag |= CS7; //7 data bits
Odd parity (7O1):
options.c_cflag |= PARENB; //with parity
options.c_cflag |= PARODD; //odd parity
options.c_cflag &= ~CSTOPB; //one stop bit
options.c_cflag &= ~CSIZE; //no bit mask
options.c_cflag |= CS7; //7 data bits
CSIZE ——bit mask for data bits
CS7——7 data bits
CS8——8 data bits
CSTOPB——2 stop bits (1 otherwise)
PARENB——enable parity
PARODD——use odd parity instead of even
1.6 Read and write serial port
After setting up the serial port, it is very easy to read and write the serial port. You can read and write the serial port as a file
Send data:
char buffer[1024];
int Length=1024;
int nByte;
nByte = write(fd, buffer ,Length)
Use the file operation read function to read. If the raw mode (Raw Mode) is set to transmit data, the number of characters returned by the read function is the number of characters actually received by the serial port.
char buff[1024];
int Len=1024;
int readByte = read(fd, buff, Len);
2. Specific Programming
The specific program is in the code directory. There are a few points that need special attention.
options.c_iflag &= ~ (IXON | IXOFF | IXANY); The VSTART and VSTOP elements of the c_cc array are set to DC1 and DC3, representing the XON and XOFF characters of the ASCII standard. If these two characters cannot be transmitted, the software flow control needs to be disabled.
options.c_lflag &= ~ (ICANON | ECHO | ECHOE | ISIG);
Sometimes, when sending data with write, if you do not type a carriage return, the information will not be sent out. This is mainly because we follow the standard mode when sending and receiving carriage returns or line feeds, but in most cases we do not need to type a carriage return or line feed. In this case, you should switch to line mode input and send it directly without processing.
options.c_iflag &= ~ (INLCR | ICRNL | IGNCR); options.c_oflag &= ~(ONLCR | OCRNL);
There is also such a situation: when sending the character 0X0d, the character received by the receiving end is often 0X0a. The reason is that in the serial port settings, there is a mapping from NL-CR and CR-NL in c_iflag and c_oflag, that is, the serial port can treat carriage return and line feed as the same character. You can set it as follows to block it:
3. The above serial ports are suitable for general-purpose processors such as AM335x, AM62x, G2L, etc.
For example, the Visionox AM62x core board is an industrial-grade core board designed based on the TI AM62x processor and is widely used in various serial port servers, multi-serial port gateways and other application scenarios.