As we all know, most of the devices are treated as files in Linux, so is the UART for which I will give some introduction about the programming, the operations on UART are the same as the operations on files.

1. Steps about the UART programming in Linux

  1. Open the UART
  2. Initialize the UART
  3. Read from or Write to the UART
  4. Close the UART

2. Open the UART

Since the UART is treated as file, we must open the file before any other operation is done on the file.

2.1 device name

In linux, the UART device is accessed through the device file of UART device, which means we access the UART device by accessing the device files(e.g. /dev/ttyS0, /dev/ttyS1, /dev/ttyS2)

2.2 options

Call the Open() function to open the UART device, we need to use the parameter "O_NOCTTY" when opening the UART device. O_NOCTTY: It means we have opened one terminal device, the program will not become the controlling terminal of this port, if this parameter is not used, any input will affect the process of the system. O_NDELAY: It means we don't care the status of the UART's DCD signal.

2.3. Steps of opening the UART

2.3.1 open()

Open the UART by calling the function Open(), the returned value is the file descriptor.

2.3.2 fcntl()

Get the status of the UART, make sure whether the mode is blocked or not.

2.3.3 isatty()

Test whether the opened file descriptor is terminal device or not.

2.3.4 Function

int UART0_Open(int fd, char *port)
{
	fd = open(port, O_RDWR|O_NOCTTY|O_NDELAY);
	if(fd==FALSE)
	{
		perror("Can't open the serial port\n");
		return(FALSE);
	}
	if(fcntl(fd, F_SETFL, 0)<0)
	{
		printf("Fcntl failed\n");
		return(FALSE);
	}
	else
	{
		printf("Fcntl=%d\n", fcntl(fd,F_SETFL,0));
	}
	if(isatty(STDIN_FILENO)==0)
	{
		printf("Standard input is not a terminal device\n");
		return(FALSE);
	}
	else
	{
		printf("Isatty success\n");
	}
	printf("fd->open=%d\n", fd);
	return(fd);
}

3. Initialize the UART

In order to initialize the UART into a workable status, it's necessary to configure the UART with suitable baudrate, flow control, frame format(e.g. data bits, stop bit, parity bit).

3.1 Steps of initializing the UART

3.1.1 Set the baudrate
3.1.2 Set the data flow control
3.1.3 Set the frame format

We will use the data structure 'termios' to set the UART, first of all, we need to get the data point which points to the structure of the termios by calling the function tcgettattr(fd, &options). We can set the data bits by modifying the c_flag of the termios structure, CS5 means 5 data bits, CS6 means 6 data bits and so forth, remember to use CSIZE as the mask. Data flow control determins which flag we will use to mark the start and stop of the data transferring. After the above steps, we still need to set the minimum waiting time and minimum receiving data bytes. Finally we need to call tcsetattr() to active the configuration.

3.1.4 Function

int UART0_Set(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity)
{
	int i;
	int status;
	int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300};
	int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300};
	struct termios options;
	if(tcgetattr(fd, &options)!=0)
	{
		perror("Setup UART\n");
		return(FALSE);
	}

	for( i=0; i < sizeof(speed_arr)/sizeof(int); i++)
	{
		if(speed == name_arr[i])
		{
			cfsetispeed(&Options, speed_arr[i]);
			cfsetospeed(&Options, speed_arr[i]);
		}
	}     

	options.c_cflag |= CLOCAL;
	options.c_cflag |= CREAD;

	switch(flow_ctrl)
	{
		case 0:	// No flow control is used
			options.c_cflag &= ~CRTSCTS;
			break;
		case 1:	// Hardware flow control
			options.c_cflag |= CRTSCTS;
			break;
		case 2:	// Software flow control
			options.c_cflag |= IXON | IXOFF | IXANY;
			break;
	}

	options.c_cflag &= ~CSIZE;	// Mask other flag bits
	switch (databits)
	{
		case 5:
			options.c_cflag |= CS5;
			break;
		case 6:
			options.c_cflag |= CS6;
			break;
		case 7:
			options.c_cflag |= CS7;
			break;
		case 8:    
			options.c_cflag |= CS8;
			break;  
		default:   
			fprintf(stderr, "Unsupported data size\n");
			return(FALSE);
	}

	switch(parity)
	{  
		case 'n':
		case 'N':	//No Parity bit
			options.c_cflag &= ~PARENB; 
			options.c_iflag &= ~INPCK;    
			break; 
		case 'o':  
		case 'O':	//Odd parity check
			options.c_cflag |= (PARODD | PARENB); 
			options.c_iflag |= INPCK;             
			break; 
		case 'e': 
		case 'E':	//Even parity check
			options.c_cflag |= PARENB;       
			options.c_cflag &= ~PARODD;       
			options.c_iflag |= INPCK;       
			break;
		case 's':
		case 'S':	//Space
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;
			break; 
		default:  
			fprintf(stderr, "Unsupported parity\n");   
			return(FALSE); 
	} 

	//Set stop bit
	switch (stopbits)
	{  
		case 1:   
			options.c_cflag &= ~CSTOPB; 
			break; 
		case 2:   
			options.c_cflag |= CSTOPB; 
			break;
		default:   
			fprintf(stderr,"Unsupported stop bits\n"); 
		return (FALSE);
	}

    //Modify output mode, RAW data mode
	options.c_oflag &= ~OPOST;

	//set the minimum waiting time and minimum receiving bytes before unblocking
	options.c_cc[VTIME] = 1;
	options.c_cc[VMIN] = 1;

	tcflush(fd,TCIFLUSH);
	//active the configuration
	if(tcsetattr(fd, TCSANOW, &options) != 0)
	{
		perror("com set error!\n");  
		return (FALSE); 
	}

	return(TRUE);
}

4. Read and Write function

4.1 Read() and Write()

Reading from and Writing to UART is implemented by using Read() and Write() functions.

4.2 program


int UART0_Recv(int fd, char *rcv_buf, int data_len)
{
	int len,fs_sel;
	fd_set fs_read;
	struct timeval time;

	FD_ZERO(&fs_read);
	FD_SET(fd, &fs_read);

	time.tv_sec = 10;
	time.tv_usec = 0;

	// Using Select() function to realize the multiply channels' communication

	fs_sel = select(fd+1, &fs_read, NULL, NULL, &time);
	if(fs_sel)
	{
		len = read(fd, data, data_len);
		return(len);
	}
	else
	{
		return(FALSE);
	}     
}
int UART0_Send(int fd, char *send_buf, int data_len)
{
	int len = 0;
	len = write(fd, send_buf, data_len);
	if(len == data_len)
	{
		return(len);
	}     
	else
	{
		tcflush(fd,TCOFLUSH);
		return(FALSE);
	}
}

5. Close the UART

We must close the UART after using it, following is the implementation of the close action.


void UART0_Close(int fd)
{
	close(fd);
}

Files:
Date 2018-07-29
File Size 2.86 KB
Download 493