2009-11-18 9 views
6

j'ai le programme C:lecture du port série échoue

#include <fcntl.h> 
#include <termios.h> 
#include <stdio.h> 

int main() 
{ 
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK); 
    if(fd < 0) 
    { 
     perror("Could not open device"); 
    } 
    printf("Device opened\n"); 

    struct termios options; 
    tcgetattr(fd, &options); 
    cfmakeraw(&options); 
    cfsetispeed(&options, B19200); 
    cfsetospeed(&options, B19200); 
    tcsetattr(fd, TCSANOW, &options); 

    char txpacket[] = {0x23, 0x06, 0x00, 0x00, 0xdd, 0xf9}; 
    ssize_t written = write(fd, txpacket, sizeof(txpacket)); 
    printf("Written %d bytes\n", written); 

    printf("Starting to wait for target to respond\n"); 
    while(1) 
    { 
     fd_set readset; 
     FD_ZERO(&readset); 
     FD_SET(fd, &readset); 
     int nCount = select(fd + 1, &readset, NULL, NULL, NULL); 
     if(nCount > 0) 
     { 
      if(FD_ISSET(fd, &readset)) 
      { 
       int i; 
       char buffer[128]; 
       ssize_t bytesread = read(fd, buffer, sizeof(buffer)); 
       printf("Received %d bytes\n", bytesread); 
       for(i = 0; i < bytesread; i++) 
       { 
        printf(" %02x", buffer[i]); 
       } 
      } 
     } 
    } 
} 

Ce programme ouvre le périphérique série/dev/ttyS0, écrit une séquence de données à l'écoute et commence une réponse. Je reçois la sortie suivante:

Device opened 
Written 6 bytes 
Starting to wait for target to respond 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
Received 0 bytes 
... 

Et l'application consomme 100% CPU. Je ne suis pas en mesure de recevoir des données, même si le matériel cible les transmet réellement.

Qu'est-ce qui ne va pas?

Répondre

7

read() renvoyer 0 indique la condition de fin de fichier. Vous devriez vérifier cela et sortir de la boucle si cela se produit. En ce qui concerne les causes de ce problème, la fin d'un fichier sur un port série indique qu'il a détecté un blocage, ce qui signifie que la ligne DCD a été supprimée.

Vous pouvez définir l'indicateur CLOCAL dans options.c_cflag pour ignorer les lignes de contrôle du modem si votre périphérique ne les a pas définies correctement.

+0

Merci! C'était en effet ce qui causait le problème. – anorm

+0

Merde, n'a pas vu la chose CLOCAL! – shodanex

+0

Avait le même problème, merci pour le conseil. N'a pas réalisé cfmakeraw dind't voir ces deux drapeaux évidents. – RishiD

1

Vous devriez essayer sans le drapeau O_NONBLOCK. en mode brut, si les paramètres de c_cc[VMIN] et c_cc[VTIME] est 0, le port série se comporte comme celui-ci (selon cfmakeraw homme):

Si les données sont disponibles, lisez les retours immédiatement, avec le moindre du nombre d'octets disponibles ou nombre d'octets requis. Si aucune donnée est disponible, de lecture renvoie 0

Donc ce que vous devriez essayer est:

options->c_cc[VMIN]=1; 
+0

Vraiment bonne note sur un coin bizarre. – Joe