2012-07-31 10 views
8

के लिए चुनिंदा() का उपयोग करना मैं एक ऐसे प्रोजेक्ट पर काम कर रहा हूं जिसमें मुझे सीरियल पोर्ट से डेटा पढ़ने और लिखने की ज़रूरत है, और इसके कारणों में गैर-अवरुद्ध होने की आवश्यकता है क्योंकि मैं नहीं जाऊंगा। चयन() फ़ंक्शन ऐसा लगता है जो मैं उपयोग करना चाहता हूं, लेकिन मैं कामकाजी कार्यान्वयन के साथ संघर्ष कर रहा हूं।नॉनब्लॉकिंग सीरियल

open_port() में मैं बंदरगाह के लिए सेटिंग्स को परिभाषित करता हूं और यह गैर-अवरुद्ध है। अन्य चयन में() मैं descriptor को open_port() में पढ़ता हूं और पढ़ने का प्रयास करता हूं। हार्डवेयर के लिए पढ़ने के लिए तेजी से पढ़ने से बचने के प्रयास में मेरे पास फ़ंक्शन के अंत में 1 सेकंड की नींद कॉल भी है।

चलते समय मुझे संदेश भेजने से पहले "कोई डेटा उपलब्ध नहीं" के लिए प्रत्येक सेकेंड में एक संदेश प्रिंटिंग मिलता है, और जब मैं एक संदेश भेजता हूं तो यह प्रिंट करता है, लेकिन आमतौर पर इसके साथ बाइनरी वर्णों के टुकड़े होते हैं। उदाहरण के लिए, "बफर" शब्द भेजते समय यह एक बाइनरी चरित्र के बाद "फेफर" प्रिंट करेगा।

मुझे टर्मियो या चयन के साथ लगभग कोई अनुभव नहीं है, इसलिए किसी भी सुझाव की सराहना की जाएगी।

#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

क्योंकि यह सी ++ है, क्या आपने इसके लिए boost :: asio का उपयोग करने पर विचार किया है? – moooeeeep

+0

क्या आपको अपने ओपन() कॉल में 'O_NONBLOCK' की आवश्यकता नहीं होगी, वास्तव में इसे गैर-अवरुद्ध करने के लिए? संपादित करें: आईआईआरसी, 'O_NDELAY' बस डीसीडी के लिए इंतजार कर रहा है, जबकि' O_NONBLOCK' वास्तव में किसी भी इनपुट के इंतजार किए बिना चला जाता है। – favoretti

+0

O_NDELAY को fcntl.h में O_NONBLOCK के बराबर सेट किया गया है, वे बराबर हैं। मैंने अभी तक बूस्ट :: एएसओओ में नहीं देखा है, और मैं अब यह करूँगा, लेकिन मुझे वास्तव में विकल्प चुनने की इच्छा है कि चयन करने के लिए डेटा है() –

उत्तर

1

जब आप पढ़ उपयोग() आप एक अशक्त समाप्त स्ट्रिंग नहीं मिलता है, तो

cout<<buffer<<endl 

स्पष्ट रूप से एक बुरा विचार है। एक,

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

इसे प्रिंट करने से पहले करें।

संबंधित मुद्दे