2017-08-12 1 views
0

J'essaie de travailler avec la fonction read() avec une connexion série.Série read() ne renvoie pas de valeur sans la réception de données

I initialize port série avec les paramètres suivants:

bool HardwareSerial::begin(speed_t speed) { 


    int USB = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); 

    if (USB == 1) { 

     std::cout << "\n Error! in Opening ttyUSB0\n" << std::endl; 
    } else { 

     std::cout << "\n ttyUSB0 Opened Successfully\n" << std::endl; 
    } 

    struct termios tty; 
    struct termios tty_old; 
    memset(&tty, 0, sizeof tty); 

    // Error Handling 
    if (tcgetattr(USB, &tty) != 0) { 
     std::cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl; 
    } 

    //Save old tty parameters 
    tty_old = tty; 

    // Set Baud Rate 
    cfsetospeed(&tty, (speed_t) speed); 
    cfsetispeed(&tty, (speed_t) speed); 

    // Setting other Port Stuff 
    tty.c_cflag &= ~PARENB; // Make 8n1 
    tty.c_cflag &= ~CSTOPB; 
    tty.c_cflag &= ~CSIZE; 
    tty.c_cflag |= CS8; 

    tty.c_iflag &= ~(IXON | IXOFF | IXANY); 
    tty.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); 

    tty.c_cflag &= ~CRTSCTS; // no flow control 
    tty.c_cc[VMIN] = 1; // read doesn't block 
    tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout 
    tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines 

    // Make raw 
    cfmakeraw(&tty); 

    //Flush Port, then applies attributes 
    tcflush(USB, TCIFLUSH); 
    if (tcsetattr(USB, TCSANOW, &tty) != 0) { 
     std::cout << "Error " << errno << " from tcsetattr" << std::endl; 
    } 

    _USB = USB; 

    return true; 

} 

J'appelle lu membre de la classe périodiquement() fonction flux appelle lecture:

int HardwareSerial::read() { 

    int n = 0; 
    char buf; 

    n = ::read(_USB, &buf, 1); 

    std::cout << std::hex << static_cast<int> (buf) << " n:"; 
    std::cout << n << std::endl; 

} 

Alors que le port reçoit lecture de données() fonctionne comme prévu et imprime les octets entrants. Mais si j'arrête d'envoyer des octets, le programme se bloque jusqu'à ce que certains octets n'aient pas été reçus. Je m'attends à ce que :: read renvoie 0, mais il ne renvoie rien et attend les données entrantes. Après la réception de nouvelles données, le programme continue à fonctionner et :: read renvoie 1;

Donc ce que j'ai manqué dans la configuration? J'ai essayé différents VMIN et VTIME mais le résultat est le même.

Répondre

4

Vous lisez de la manière USB de manière bloquante, par ex. Si aucune donnée n'est disponible, l'appel est bloqué et le processus ne progressera pas avant l'arrivée des données.

Que peut-on faire, vous pouvez définir le descripteur à lire en mode NON-BLOCKING, quelque chose le long de ces lignes:

int flags = fcntl(_USB, F_GETFL, 0); 
fcntl(_USB, F_SETFL, flags | O_NONBLOCK) 

Maintenant que vous allez essayer de vous lire pouvez faire:

int count; 
char buffer; 
count = read(_USD, buf, 1); 
// Check whenever you succeeded to read something 
if(count >=0) { 
    // Data is arrived 
} else if(count < 0 && errno == EAGAIN) { 
    // No Data, need to wait, continue, or something else. 
} 

Vous pouvez également utiliser probablement la fonction select pour vérifier à quel moment le descripteur de périphérique est prêt à lire.