2009-11-18 18 views
6

ho il seguente programma C:lettura dalla porta seriale fallisce

#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]); 
       } 
      } 
     } 
    } 
} 

Questo programma apre il dispositivo seriale/dev/ttyS0, scrive una sequenza di dati ad esso e si mette in ascolto di una risposta. Ottengo il seguente risultato:

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 
... 

E l'applicazione consuma CPU al 100%. Non sono in grado di ricevere alcun dato, anche se l'hardware di destinazione effettivamente lo trasmette.

Cosa c'è che non va?

risposta

7

read() restituendo 0 indica la condizione di fine file. Dovresti controllarlo e uscire dal ciclo se si verifica.

Per quanto riguarda ciò che sta causando che - la fine del file su una porta seriale indica che ha rilevato un blocco, ovvero che la linea DCD è stata eliminata.

È possibile impostare il flag CLOCAL in options.c_cflag per ignorare le linee di controllo del modem, se il dispositivo non le imposta correttamente.

+0

Grazie! Questo era davvero ciò che stava causando il problema. – anorm

+0

Dannazione, non ho visto la cosa di CLOCAL! – shodanex

+0

Aveva lo stesso problema, grazie per il suggerimento. Non sapevo che cfmakeraw non avrebbe visto quelle due bandiere evidenti. – RishiD

1

Si dovrebbe provare senza il flag O_NONBLOCK. in modalità raw, se le impostazioni di c_cc[VMIN] e c_cc[VTIME] è 0, la porta seriale comporta così (secondo l'uomo cfmakeraw):

Se i dati sono disponibili, read ritorna immediatamente, con minore del numero di byte disponibili o il numero di byte richiesto. Se non ci sono dati è disponibile, leggere restituisce 0

Che cosa si dovrebbe provare è:

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

Davvero una buona nota su un caso d'angolo strano. – Joe

Problemi correlati