Linux serial port application programming

1. Serial port API

insert image description here
In the Linux system, the unified interface for operating devices is: open/ioctl/read/write.
For UART, many functions are encapsulated on top of ioctl, which are mainly used to set line procedures.
So for UART, the programming routine is:

  • open
  • Set line procedures, such as baud rate, data bits, stop bits, check bits, RAW mode, return as soon as there is data
  • How to set the line procedure for read/write
    ? The parameters of the line procedure are represented by the structure termios, you can refer to the Linux serial port—struct termios structure
typedef unsigned char 	cc_t;
typedef unsigned int 	speed_t;
typedef unsgined int 	tcflag_t;

#define NCCS 19
struct termios {
    
    
	tcflag_t c_iflag;		/* input mode flags */
	tcflag_t c_oflag;		/* output mode flags */
	tcflag_t c_cflag;		/* control mode flags */
	tcflag_t c_lflag;		/* local mode flags */
	cc_t c_line;			/* line discipline */
	cc_t c_cc[NCCS];		/* control characters */
};

These functions have some conventions in their names:

  • tc: terminal control
  • cf: control flag
Function name effect
tcgetattr get terminal attributes, get the attributes of the terminal
tcsetattr set terminal attributes, modify terminal parameters
tcflush Clear the terminal's unfinished input/output requests and data
cfsetispeed sets the input baud rate, set the input baud rate
cfsetospeed sets the output baud rate, set the output baud rate
cfsetspeed Simultaneously set the input and output baud rate

There are not many functions, the main thing is to set the parameters in termios. These parameters are very complicated. You can refer to the Linux serial port—struct termios structure .

Two, programming

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>

int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
    
    
	struct termios newtio, oldtio;
	
	if(tcgetattr(fd, &oldtio) != 0) {
    
    
		perror("SetupSerial 1");
		return -1;
	}

	bzero(&newtio, sizeof(newtio));
	newtio.c_cflag |= CLOCAL|CREAD;
	newtio.c_cflag &= ~CSIZE;

	newtio.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG);
	newtio.c_oflag &= ~OPOST;

	switch(nBits) {
    
    
	case 7:
		newtio.c_cflag |= CS7;
		break;
	case 8:
		newtio.c_cflag |= CS8;
		break;
	}

	switch(nEvent) {
    
    
	case 0:
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'E':
		newtio.c_iflag |= (INPCK|ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':
		newtio.c_cflag &= ~PARENB;
		break;
	}

	switch(nSpeed) {
    
    
	case 2400:
		cfsetispeed(&newtio, B2400);
		cfsetospeed(&newtio, B2400);
		break;
	case 4800:
		cfsetispeed(&newtio, B4800);
		cfsetospeed(&newtio, B4800);
		break;
	case 9600:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	case 115200:
		cfsetispeed(&newtio, B115200);
		cfsetospeed(&newtio, B115200);
		break;
	default:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	}


	if(nStop == 1)
		newtio.c_cflag &= ~CSTOPB;
	else if(nStop == 2)
		newtio.c_cflag |= CSTOPB;

	newtio.c_cc[VMIN] = 1;
	newtio.c_cc[VTIME] = 0;

	tcflush(fd, TCIFLUSH);
	if((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
    
    
		perror("com set error");
		return -1;
	}

	return 0;
}

int open_port(char *com)
{
    
    
	int fd;
	fd = open(com, O_RDWR|O_NOCTTY);
	if(-1 == fd) {
    
    
		return -1;
	}

	if(fcntl(fd, F_SETFL, 0) < 0) {
    
    
		printf("fcntl failed\n");
		return -1;
	}
	return fd;
}

int main(int argc, char *argv[])
{
    
    
	int fd;
	int iRet;
	char c;

	if(argc != 2) {
    
    
		printf("Usage: \n");
		printf("%s </dev/ttySAC1 or other>\n", argv[0]);
		return -1;
	}

	fd = open_port(argv[1]);
	if(fd < 0) {
    
    
		printf("open %s err!\n", argv[1]);
		return -1;
	}

	iRet = set_opt(fd, 115200, 8, 'N', 1);
	if(iRet) {
    
    
		printf("set port err!\n");
		return -1;
	}

	printf("Enter a char: ");
	while(1) {
    
    
		scanf("%c", &c);
		iRet = write(fd, &c, 1);
		iRet = read(fd, &c, 1);
		if(iRet == 1) {
    
    
			printf("get: %02x %c\n", c, c);
		} else {
    
    
			printf("can not get data\n");
		}
	}

	return 0;
}

3. Computer experiment

Short the RX and TX of the serial port

root@npi:~/test# ./a.out /dev/ttymxc2 
Enter a cahr: a
get: 61 a
get: 0a 


get: 0a 

 
get: 0a 

a 
get: 61 a
get: 0a 

Guess you like

Origin blog.csdn.net/ch122633/article/details/129596576