1.对于在uart在linux上面的使用有几个地方需要注意的
a.输入数据格式的设置(使用read()函数时)
设置方式:
/*Canonical Input*/
//termios_new.c_lflag |= (ICANON | ECHO | ECHOE);
/*Raw Input*/
//termios_new.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
这两个方式有很大的差别:
Raw Inpu模式:基本就是跟普通单片机一样Rx端接收到什么直接返回到用户空间的read函数里面。
Canonical Input模式:Rx端接收到数据之后不会直接反馈给用户态的read函数而是要一直等到一个回车,才会将数据发送到用户空间,还有一个地方需要注意的是,Rx上面接收到的每一个字符都会通过Tx发送出去,这个是由内核控制的,不受用户态控制,这个模式的典型应用就是linux的console。
2.VTIME和VMIN 决定了read()函数什么时候返回
1.当VTIME>0,VMIN>0时。read调用将保持阻塞直到读取到第一个字符,读到了第一个字符之后开始计时,此后若时间到了VTIME或者时间未到但已读够了VMIN个字符则会返回;若在时间未到之前又读到了一个字符(但此时读到的总数仍不够VMIN)则计时重新开始。
2. 当VTIME>0,VMIN=0时。read调用读到数据则立即返回,否则将为每个字符最多等待VTIME时间。
3. 当VTIME=0,VMIN>0时。read调用一直阻塞,直到读到VMIN个字符后立即返回。
4. 若在open或fcntl设置了O_NDELALY或O_NONBLOCK标志,read调用不会阻塞而是立即返回,那么VTIME和VMIN就没有意义,效果等同于与把VTIME和VMIN都设为了0。
VTIME 和 VMIN
VTIME 定义要求等待的零到几百毫秒的值(通常是一个8位的unsigned char变量)。
VMIN 定义了要求等待的最小字节数, 这个字节数可能是0。
只有设置为阻塞时这两个参数才有效,仅针对于读操作。
说起来比较复杂,举个例子吧,设置为阻塞状态,写操作未进行实验,这里仅讨论读操作,
read(fd,&buf,8); // 读串口
1、
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
VMIN = 0,当缓冲区字节数 >= 0 时进行读操作,实际上这时读串口操作并未被阻塞,因为条件始终被满足。
2、
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 1;
VMIN = 1,当缓冲区字节数 >= 1 时进行读操作,当没有数据时读串口操作被阻塞。
3、
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 4;
VMIN = 4,当缓冲区字节数 >= 4 时进行读操作,否则读串口操作被阻塞。每次读出的最大字节数由read函数中第三个参数决定。直到缓冲区剩下的数据< read 第三个参数 并且< 4 (如果这时read第三参数为 1 则进行4次读操作直至读完缓冲区,如read第三参数为2,连续进行读操作,直至缓冲区空或还剩一个字符)。没有设置VTIME,剩下的字符没有确定的期限,直到下次满足读条件的时候才被读出。
4
options.c_cc[VTIME] = 10; //单位百毫秒
options.c_cc[VMIN] = 4;
同3的区别就是,没满足条件或读缓冲区中剩下的数据会在1秒(10百毫秒)后读出。另外特别注意的是当设置VTIME后,如果read第三个参数小于VMIN ,将会将VMIN 修改为read的第三个参数,即,使用read(fd,&buf,2);,以上设置变为:
options.c_cc[VTIME] = 10;
options.c_cc[VMIN] = 2;
下面给一个example code:将开发板的tx,rx分别接到pc端usb转串口的rx,tx端,通过串口助手将数据发送到开发板上面,开发板会将接收到的数据返回给串口助手。
参考:https://blog.csdn.net/qq_21593899/article/details/52281034
#include
#include /* File Control Definitions */
#include /* POSIX Terminal Control Definitions */
#include /* UNIX Standard Definitions */
#include /* ERROR Number Definitions */
int uart_int(void)
{
int fd;/*File Descriptor*/
/*------------------------------- Opening the Serial Port -------------------------------*/
fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY | O_NDELAY); /* ttyUSB0 is the FT232 based USB2SERIAL Converter |O_NDELAY */
/* O_RDWR - Read/Write access to serial port */
/* O_NOCTTY - No terminal will control the process */
/* Open in blocking mode,read will wait */
if(fd == -1) /* Error Checking */
{
printf("\n Error! in Opening ttyUSB0 ");
return -1;
}
else
{
printf("\n ttyUSB0 Opened Successfully ");
}
/*---------- Setting the Attributes of the serial port using termios structure --------- */
/*RX init*/
struct termios SerialPortSettings; /* Create the structure */
tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */
/* Setting the Baud rate */
cfsetispeed(&SerialPortSettings, B115200); /* Set Read Speed as 9600 */
cfsetospeed(&SerialPortSettings, B115200); /* Set Write Speed as 9600 */
/* 8N1 Mode */
SerialPortSettings.c_cflag &= ~PARENB; /* Disables the Parity Enable bit(PARENB),So No Parity */
SerialPortSettings.c_cflag &= ~CSTOPB; /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the mask for setting the data size */
SerialPortSettings.c_cflag |= CS8; /* Set the data bits = 8 */
SerialPortSettings.c_cflag &= ~CRTSCTS; /* No Hardware flow Control */
SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines */
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); /* Disable XON/XOFF flow control both i/p and o/p */
SerialPortSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode */
SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing raw format output*/
/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 0; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 1; /* Wait indefinetly */
if((tcsetattr(fd, TCSANOW, &SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
printf("\n ERROR ! in Setting attributes");
else
printf("\n BaudRate = 115200 \n StopBits = 1 \n Parity = none");
/*------------------------------- Read data from serial port -----------------------------*/
tcflush(fd, TCIFLUSH); /* Discards old data in the rx buffer */
close(fd); /* Close the serial port */
return 0;
}
int main(void)
{
int fd;/*File Descriptor*/
printf("\n +----------------------------------+");
printf("\n | Serial Port Read |");
printf("\n +----------------------------------+");
uart_int();
/*------------------------------- Opening the Serial Port -------------------------------*/
fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY | O_NDELAY); /* ttyUSB0 is the FT232 based USB2SERIAL Converter */
/* O_RDWR - Read/Write access to serial port */
/* O_NOCTTY - No terminal will control the process */
/* Open in blocking mode,read will wait */
if(fd == -1) /* Error Checking */
printf("\n Error! in Opening ttyUSB0 ");
else
printf("\n ttyUSB0 Opened Successfully ");
char read_buffer[32]; /* Buffer to store the data received */
int bytes_read = 0; /* Number of bytes read by the read() system call */
int i = 0;
while(1)
{
bytes_read = read(fd, &read_buffer, 32); /* Read the data */
if(bytes_read > 0)
{
printf("\n\n Bytes Rxed -%d", bytes_read); /* Print the number of bytes read */
printf("\n\n ");
for(i = 0; i < bytes_read; i++) /*printing only the received characters*/
printf("%c", read_buffer[i]);
int bytes_written = 0; /* Value for storing the number of bytes written to the port */
bytes_written = write(fd, read_buffer, bytes_read); /* use write() to send data to port */
/* "fd" - file descriptor pointing to the opened serial port */
/* "write_buffer" - address of the buffer containing data */
/* "sizeof(write_buffer)" - No of bytes to write */
printf("\n %d Bytes written to ttyUSB0", bytes_written);
printf("\n\n Bytes Rxed -%d", bytes_read); /* Print the number of bytes read */
printf("\n\n ");
printf("\n +----------------------------------+\n\n\n");
}
//sleep(1);
}