Lendo e escrevendo de/para ttyS0

Lendo e escrevendo de/para ttyS0

Tenho um Raspberry PI Zero W conectado à minha máquina virtual via USB, que pode ser encontrado /dev/ttyS0no PC e no RPI. Atualmente estou tentando enviar algo do RPI através do cabo USB para a máquina virtual (PC).

Estou tentando ler na porta com o seguinte código:

    #include <stdio.h>   /* Standard input/output definitions */    
    #include <string.h>  /* String function definitions */    
    #include <unistd.h>  /* UNIX standard function definitions */    
    #include <fcntl.h>   /* File control definitions */    
    #include <errno.h>   /* Error number definitions */    
    #include <termios.h> /* POSIX terminal control definitions */    

    /*     * 'open_port()' − Open serial port 1.     *     
    * Returns the file descriptor on success or −1 on error.     */    

   int fd; /* File descriptor for the port */

   int open_port(void)    
   {            
     fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);   

     if(fd == -1) 
     {       
       /*        * Could not open the port.        */        
       perror("open_port: Unable to open /dev/ttyS0 − ");      
     }      
     else        
      fcntl(fd, F_SETFL, FNDELAY);      

    return (fd);    
  }

  int close_port(void)
  {
    close(fd);
    return (fd);
  }


  int main()
  {
    printf("Serial reader has started...\n\n");
    while(1)
    {
      open_port();
      close_port();
    }

    return 0;
  }

e do lado RPI, fiz um pequeno script bash, que envia o caractere 1:

while :
do
    echo "sending character 1 to /dev/ttyS0"
    echo "1" > /dev/ttyS0
done

No entanto, embora o script bash e o programa c estejam sendo executados em loops contínuos, não estou recebendo nada do lado do PC.

Qual seria a razão?

OBSERVAÇÃO: O RPI pode ser acessado via USB da VM, pois estou usando SSH na VM para acessar o RPI. Então sim, a VM já deve estar configurada para acessar a porta USB.

EDITAR: Tentei alterar o código para este, onde implementei a função read(), porém ainda não vejo nenhuma alteração:

    #include <stdio.h>   /* Standard input/output definitions */    
    #include <string.h>  /* String function definitions */    
    #include <unistd.h>  /* UNIX standard function definitions */    
    #include <fcntl.h>   /* File control definitions */    
    #include <errno.h>   /* Error number definitions */    
    #include <termios.h> /* POSIX terminal control definitions */    

    /*     * 'open_port()' − Open serial port 1.     *     
    * Returns the file descriptor on success or −1 on error.     */    

   int fd; /* File descriptor for the port */
   unsigned char bufptr;
   int reader;

   int open_port(void)    
   {            
     fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);   

     if(fd == -1) 
     {       
       /*        * Could not open the port.        */        
       perror("open_port: Unable to open /dev/ttyS0 − ");      
     }      
     else
     {        
      fcntl(fd, F_SETFL, FNDELAY);
      reader = read(fd, &bufptr, 1);
        if (reader > 0)
        {
          write(STDOUT_FILENO, &bufptr, 1);  
        }
     }

    return (fd);    
  }

  int close_port(void)
  {
    close(fd);
    return (fd);
  }


  int main()
  {
    printf("Serial reader has started...\n\n");
    while(1)
    {
      open_port();
      close_port();
    }

    return 0;
  }

Responder1

Na sua edição, você adicionou o código para ler da porta à open_port()função. Embora pareça que pode funcionar, isso é um mau estilo: agora a open_port()função é específica para as necessidades deste programa e não é mais fácil de escolher e reutilizar em algum projeto futuro sem modificações. E o nome da função não descreve mais com precisão o que a função faz.

Não estou convencido de que a configuração da sua conexão serial esteja correta: você diz que está usando uma VM e que há USB envolvido, mas parece estar usando /dev/ttyS0nas duas extremidades. Isso se refere a uma porta serial física, não a uma porta USB.

Talvez você tenha configurado seu software de virtualização para conectar uma porta serial física real ou uma porta serial gerada pelo driver conversor serial USB do host às VMs /dev/ttyS0: se isso for verdade, então isso pode funcionar no lado do PC. Mas isso énão é o padrão: você deve definitivamente configurar isso em seu software de virtualização ou então não funcionará.

Uma configuração mais comum seria configurar o software de virtualização para permitir que a VM acesse o lado USB de um conversor serial USB como um todo: então ele apareceria na VM como algo parecido /dev/ttyUSB0(dependendo do tipo exato da serial conversor).

Do lado RasPi,/dev/ttyS0 não existena configuração padrão do Pi Zero W - a porta serial típica é /dev/ttyAMA0, mas na configuração padrão ela é usada pela funcionalidade Bluetooth. Se você conectou o lado USB do conversor serial USB ao RasPi, ele /dev/ttyUSB0também aparecerá como aqui.

Como o script do lado RasPi não verifica a existência do dispositivo, ele pode ter criado um arquivo chamado /dev/ttyS0, contendo uma única linha com um número 1. Execute este comando no RasPi para ver se é /dev/ttyS0um dispositivo serial válido:

 test -c /dev/ttyS0 && echo "Maybe valid" || echo "Definitely not correct"

Se você estiver usando uma conexão serial física ( /dev/ttyS0ou /dev/ttyAMA0) no lado RasPi, você deve ter um conector de 40 pinos no RasPi Zero W soldado e algo conectado aos pinos 8 e 10 desse conector, pelo que entendi. Você também teria que usar raspi-configpara habilitar o acesso à porta serial.

Se você puder acessar o RasPi com SSH, isso significa que você tem umredeconexão: não diz absolutamente nada sobre o estado de umserialconexão.

informação relacionada