2009-11-18 33 views
6

tengo el siguiente programa en C:lectura desde el puerto serie falla

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

Este programa se abre el dispositivo serie/dev/ttyS0, escribe una secuencia de datos en él y comienza a escuchar una respuesta. Obtengo la siguiente salida:

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

Y la aplicación consume 100% de CPU. No puedo recibir ningún dato, aunque el hardware de destino realmente lo transmita.

¿Qué pasa?

Respuesta

7

read() devolver 0 indica la condición de fin de archivo. Debería verificar eso y salir del circuito si ocurre.

En cuanto a lo que está causando que - al final de su archivo en un puerto de serie indica que se ha detectado un cuelgue, lo que significa que la línea DCD se ha caído.

Puede establecer el indicador CLOCAL en options.c_cflag para ignorar las líneas de control del módem, si su dispositivo no las configura correctamente.

+0

Gracias! Eso fue de hecho lo que estaba causando el problema. – anorm

+0

¡Maldición, no vi lo de CLOCAL! – shodanex

+0

Tuve el mismo problema, gracias por la sugerencia. No me di cuenta de que cfmakeraw no veía esas dos banderas obvias. – RishiD

1

Usted debe tratar sin la bandera O_NONBLOCK. en modo raw, si la configuración de c_cc[VMIN] y c_cc[VTIME] es 0, el puerto serie se comportan como esto (según el hombre cfmakeraw):

Si se dispone de datos, leer declaraciones de inmediatamente, con el menor entre el número de bytes disponibles, o el número de bytes solicitados. Si no hay datos está disponible, lea devuelve 0

Así que lo que debe tratar es:

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

Nota realmente buena en una caja de esquina extraña. – Joe

Cuestiones relacionadas