2012-07-31 63 views
8

我正在研究一个需要从串口读取和写入数据的项目,并且由于我不会涉及的原因,这需要非阻塞。 select()函数看起来像我想使用的,但我努力获得一个工作实现。使用select()for nonblocking serial

在open_port()中,我定义了端口的设置并且它是非阻塞的。在otherselect()中,我将描述符分配给open_port()并尝试读取。我还在功能结束时进行了1秒的睡眠呼叫,以避免硬件读数过快​​。

运行时,我收到一条消息,在发送消息之前每秒都会打印出“没有数据可用”的消息,并且在我发送消息后将其打印出来,但它通常与二进制字符一起显示为碎片。例如,当发送单词“缓冲区”时,它将打印“ffer”后跟一个二进制字符。

我几乎没有经验termios或选择,所以任何建议,将不胜感激。

#include <iostream> 
#include "stdio.h" 
#include "termios.h" 
#include "errno.h" 
#include "fcntl.h" 
#include "string.h" 
#include "time.h" 
#include "sys/select.h" 

using namespace std; 

int open_port(){ 
struct termios oldtio,newtio; 
int serial_fd; 
if ((serial_fd = open("/dev/ttyS0", O_RDWR | O_EXCL | O_NDELAY)) == -1) { 
    cout << "unable to open" << endl; 
    return -1; 
} 
if (tcgetattr(serial_fd, &oldtio) == -1) { 
    cout << "tcgetattr failed" << endl; 
    return -1; 
} 
cfmakeraw(&newtio); // Clean all settings 
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | B115200; // 8 databits 
newtio.c_cflag |= (CLOCAL | CREAD); 
newtio.c_cflag &= ~(PARENB | PARODD); // No parity 
newtio.c_cflag &= ~CRTSCTS; // No hardware handshake 
newtio.c_cflag &= ~CSTOPB; // 1 stopbit 
newtio.c_iflag = IGNBRK; 
newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // No software handshake 
newtio.c_lflag = 0; 
newtio.c_oflag = 0; 
newtio.c_cc[VTIME] = 1; 
newtio.c_cc[VMIN] = 60; 
if (tcsetattr(serial_fd, TCSANOW, &newtio) == -1) { 
    cout << "tcsetattr failed" << endl; 
    return -1; 
} 
tcflush(serial_fd, TCIOFLUSH); // Clear IO buffer 
return serial_fd; 
} 

void otherselect(){ 
fd_set readfs; 
timeval tv; 
tv.tv_sec = 1; 
tv.tv_usec = 0; 
char * buffer = new char[15]; 
int _fd = open_port(); 
FD_ZERO(&readfs); 
FD_SET(_fd, &readfs); 
select(_fd+1, &readfs, NULL, NULL, &tv /* no timeout */); 
if (FD_ISSET(_fd, &readfs)) 
{ 
    int r = read(_fd, buffer, 15); 
    if(r == -1){ 
     cout << strerror(errno) << endl; 
    } 
    cout << buffer << endl; 
} 
else{ 
    cout << "data not available" << endl; 
} 
close(_fd); 
sleep(1); 
} 

int main() { 
    while(1){ 
     otherselect(); 
    } 
} 
+0

因为它的C++,你有没有考虑使用boost :: asio这个? – moooeeeep 2012-07-31 21:12:51

+0

难道你不需要'O_NONBLOCK'来打开你的open()调用来实现它的非阻塞吗?编辑:IIRC,'O_NDELAY'只是跳过等待DCD,而'O_NONBLOCK'实际上只是等待任何输入。 – favoretti 2012-07-31 21:13:33

+0

在fcntl.h中将O_NDELAY设置为等于O_NONBLOCK,它们是相等的。我还没有看过boost :: asio,现在我会这样做,但我真的很喜欢在如何处理数据时如何处理select() – 2012-07-31 21:18:44

回答

1

当你使用read(),你没有得到一个空结束的字符串,所以

cout<<buffer<<endl 

显然是一个坏主意。 做一个,

buffer[r]='\0' #(provided r<15) 

打印出来之前。