Linux 从串口读取数据
Linux Reading Data from UART
我想从 UART 读取数据,我遵循了 this tutorial,写入功能按预期工作,但是我遇到了读取功能的问题:
这是 uart_init 函数:
void uart_init()
{
printf("\n +----------------------------------+");
printf("\n | Serial Port Write |");
printf("\n +----------------------------------+");
/*------------------------------- Opening the Serial Port -------------------------------*/
fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY| O_SYNC); /* !!blocks the read */
/* O_RDWR Read/Write access to serial port */
/* O_NOCTTY - No terminal will control the process */
/* O_NDELAY -Non Blocking Mode,Does not care about- */
/* -the status of DCD line,Open() returns immediatly */
if(fd == -1) /* Error Checking */
printf("\n Error! in Opening ttyUSB0 ");
else
printf("\n ttyUSB0 Opened Successfully ");
/*---------- Setting the Attributes of the serial port using termios structure --------- */
struct termios SerialPortSettings; /* Create the structure */
tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */
cfsetispeed(&SerialPortSettings,B19200); /* Set Read Speed as 19200 */
cfsetospeed(&SerialPortSettings,B19200); /* Set Write Speed as 19200 */
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_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode */
SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/
/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 10; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* 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 = 19200 \n StopBits = 1 \n Parity = none");
}
接收函数:
void uart_receive()
{
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;
bytes_read = read(fd,&read_buffer,10); /* Read the data */
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]);
printf("\n +----------------------------------+\n\n\n");
}
主要功能:
void main(void)
{
uart_init();
/*------------------------------- Write data to serial port -----------------------------*/
//uart_write_commande(write_buffer); //Write function works well
uart_receive();
close(fd);/* Close the Serial port */
}
我执行程序并等待 UART 接收数据字节,我使用 UART 发送数据但读取功能一直被阻塞。
我正在使用装有 Ubuntu 14.04 的虚拟机,我不确定使用模拟 UART 是否会在接收过程中导致问题。
读取函数出错
bytes_read = read(fd,&read_buffer,10); /* Read the data
应该是
bytes_read = read(fd,read_buffer,10); /* Read the data
您的 read() 函数可能因任何原因被阻止。 Here is a discussion 从串行端口读取,包括 blocked/unblocked 设置的代码。
也有可能是没有数据在传输,导致什么都没有读到。在无法访问硬件设置的情况下,如果没有关于您所看到的内容的非常具体的信息,就很难更进一步。
此外,除了正确传递 read_buffer 之外(另一个答案),至少还有两件事可以改进:
1) 使用前检查read
的return:
bytes_read = read(fd,&read_buffer,10); /* Read the data*/
if(bytes_read > 0)
{
...
}
2) 变化:
for(i=0;i<bytes_read;i++) /*printing only the received characters*/
printf("%c",read_buffer[i]);
收件人:
//after successful read:
read_buffer[bytes_read]=0;//place null termination after last character read.
printf("%s",read_buffer);//note format specifier
这将打印读取的字符数,无需循环。
您的程序在 read() 系统调用中挂起,因为它被阻止等待行终止字符。
您尝试使用语句
为非规范模式配置端口
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode
但是那个操作是在错误的 termios 元素上。
ICANON 属性是 lflag 元素的一部分(而不是 iflag)。 (此错误源于您引用的教程!)
因此,您的程序正在执行阻塞规范读取。
有一个方便的 termios 函数可以配置非规范模式:
cfmakeraw() sets the terminal to something like the "raw" mode of the old
Version 7 terminal driver: input is available character by
character, echoing is disabled, and all special processing of
terminal input and output characters is disabled. The terminal
attributes are set as follows:
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios_p->c_cflag &= ~(CSIZE | PARENB);
termios_p->c_cflag |= CS8;
我想从 UART 读取数据,我遵循了 this tutorial,写入功能按预期工作,但是我遇到了读取功能的问题:
这是 uart_init 函数:
void uart_init()
{
printf("\n +----------------------------------+");
printf("\n | Serial Port Write |");
printf("\n +----------------------------------+");
/*------------------------------- Opening the Serial Port -------------------------------*/
fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY| O_SYNC); /* !!blocks the read */
/* O_RDWR Read/Write access to serial port */
/* O_NOCTTY - No terminal will control the process */
/* O_NDELAY -Non Blocking Mode,Does not care about- */
/* -the status of DCD line,Open() returns immediatly */
if(fd == -1) /* Error Checking */
printf("\n Error! in Opening ttyUSB0 ");
else
printf("\n ttyUSB0 Opened Successfully ");
/*---------- Setting the Attributes of the serial port using termios structure --------- */
struct termios SerialPortSettings; /* Create the structure */
tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */
cfsetispeed(&SerialPortSettings,B19200); /* Set Read Speed as 19200 */
cfsetospeed(&SerialPortSettings,B19200); /* Set Write Speed as 19200 */
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_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode */
SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/
/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 10; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* 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 = 19200 \n StopBits = 1 \n Parity = none");
}
接收函数:
void uart_receive()
{
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;
bytes_read = read(fd,&read_buffer,10); /* Read the data */
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]);
printf("\n +----------------------------------+\n\n\n");
}
主要功能:
void main(void)
{
uart_init();
/*------------------------------- Write data to serial port -----------------------------*/
//uart_write_commande(write_buffer); //Write function works well
uart_receive();
close(fd);/* Close the Serial port */
}
我执行程序并等待 UART 接收数据字节,我使用 UART 发送数据但读取功能一直被阻塞。
我正在使用装有 Ubuntu 14.04 的虚拟机,我不确定使用模拟 UART 是否会在接收过程中导致问题。
读取函数出错
bytes_read = read(fd,&read_buffer,10); /* Read the data
应该是
bytes_read = read(fd,read_buffer,10); /* Read the data
您的 read() 函数可能因任何原因被阻止。 Here is a discussion 从串行端口读取,包括 blocked/unblocked 设置的代码。
也有可能是没有数据在传输,导致什么都没有读到。在无法访问硬件设置的情况下,如果没有关于您所看到的内容的非常具体的信息,就很难更进一步。
此外,除了正确传递 read_buffer 之外(另一个答案),至少还有两件事可以改进:
1) 使用前检查read
的return:
bytes_read = read(fd,&read_buffer,10); /* Read the data*/
if(bytes_read > 0)
{
...
}
2) 变化:
for(i=0;i<bytes_read;i++) /*printing only the received characters*/
printf("%c",read_buffer[i]);
收件人:
//after successful read:
read_buffer[bytes_read]=0;//place null termination after last character read.
printf("%s",read_buffer);//note format specifier
这将打印读取的字符数,无需循环。
您的程序在 read() 系统调用中挂起,因为它被阻止等待行终止字符。
您尝试使用语句
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode
但是那个操作是在错误的 termios 元素上。
ICANON 属性是 lflag 元素的一部分(而不是 iflag)。 (此错误源于您引用的教程!)
因此,您的程序正在执行阻塞规范读取。
有一个方便的 termios 函数可以配置非规范模式:
cfmakeraw() sets the terminal to something like the "raw" mode of the old
Version 7 terminal driver: input is available character by
character, echoing is disabled, and all special processing of
terminal input and output characters is disabled. The terminal
attributes are set as follows:
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios_p->c_cflag &= ~(CSIZE | PARENB);
termios_p->c_cflag |= CS8;