2012-01-28 49 views
5

Estoy usando LibSerial en Ubuntu para leer y escribir datos en el puerto serie.Leer y escribir en puerto serie en Ubuntu con C/C++ y LibSerial

Por el momento, puedo escribir y recibir cadenas sobre el puerto serie, pero mi código no funciona muy bien: en particular, Me gustaría controlar la función de lectura para leer solo si hay algo que leer y salir cuando no hay información para leer para enviar otro comando sin bloquear el programa de flujo.

que quiero hacer:

  • Escriba un comando de
  • esperar la respuesta
  • luego escribir otro comando
  • esperar la contestación

Ahora, soy capaz para enviar el primer comando y leer la respuesta utilizando la función de lectura en un ciclo while, pero no puedo hacer nada más. No puedo enviar el segundo comando porque el ciclo while nunca se cierra para que el programa continúe leyendo.

¿Me puede ayudar, por favor?

Este es el código que estoy usando: (funciones de lectura y escritura están al final del código)

#include <SerialStream.h> 
#include <iostream> 
#include <unistd.h> 
#include <cstdlib> 
#include <string> 

int 
main(int argc, 
     char** argv ) 
{ 
    // 
    // Open the serial port. 
    // 
    using namespace std; 
    using namespace LibSerial ; 
    SerialStream serial_port ; 
    char c; 
    serial_port.Open("/dev/ttyACM0") ; 
    if (! serial_port.good()) 
    { 
     std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] " 
        << "Error: Could not open serial port." 
        << std::endl ; 
     exit(1) ; 
    } 
    // 
    // Set the baud rate of the serial port. 
    // 
    serial_port.SetBaudRate(SerialStreamBuf::BAUD_9600) ; 
    if (! serial_port.good()) 
    { 
     std::cerr << "Error: Could not set the baud rate." << 
std::endl ; 
     exit(1) ; 
    } 
    // 
    // Set the number of data bits. 
    // 
    serial_port.SetCharSize(SerialStreamBuf::CHAR_SIZE_8) ; 
    if (! serial_port.good()) 
    { 
     std::cerr << "Error: Could not set the character size." << 
std::endl ; 
     exit(1) ; 
    } 
    // 
    // Disable parity. 
    // 
    serial_port.SetParity(SerialStreamBuf::PARITY_NONE) ; 
    if (! serial_port.good()) 
    { 
     std::cerr << "Error: Could not disable the parity." << 
std::endl ; 
     exit(1) ; 
    } 
    // 
    // Set the number of stop bits. 
    // 
    serial_port.SetNumOfStopBits(1) ; 
    if (! serial_port.good()) 
    { 
     std::cerr << "Error: Could not set the number of stop bits." 
        << std::endl ; 
     exit(1) ; 
    } 
    // 
    // Turn off hardware flow control. 
    // 
    serial_port.SetFlowControl(SerialStreamBuf::FLOW_CONTROL_NONE) ; 
    if (! serial_port.good()) 
    { 
     std::cerr << "Error: Could not use hardware flow control." 
        << std::endl ; 
     exit(1) ; 
    } 
    // 
    // Do not skip whitespace characters while reading from the 
    // serial port. 
    // 
    // serial_port.unsetf(std::ios_base::skipws) ; 
    // 
    // Wait for some data to be available at the serial port. 
    // 
    // 
    // Keep reading data from serial port and print it to the screen. 
    // 
    // Wait for some data to be available at the serial port. 
    // 
    while(serial_port.rdbuf()->in_avail() == 0) 
    { 
     usleep(100) ; 
    } 


    char out_buf[] = "check"; 
    serial_port.write(out_buf, 5); <-- FIRST COMMAND 
    while(1 ) 
    { 
     char next_byte; 
     serial_port.get(next_byte); HERE I RECEIVE THE FIRST ANSWER 
     std::cerr << next_byte; 

    } 
    std::cerr << std::endl ; 
    return EXIT_SUCCESS ; 
} 

Respuesta

4

Creo que sólo tiene que utilizar while(serial_port.rdbuf()->in_avail() > 0) como condición para el último bucle while . Luego leerá todos los datos disponibles ("respuesta") y podrá enviar el segundo comando después de eso.

+0

El problema es que si uso ** serial_port.rdbuf() -> in_avail()> 0 ** nunca entra en el bucle while. Parece muy extraño, porque hay datos en el puerto serie pero el programa no los lee. Por el contrario, si uso ** while (1) **, lo lee correctamente. –

+0

Bien, ¿qué personaje obtienes después de leer todos los bytes de la respuesta real? Puede verificar ese carácter (creo que debería ser '\ 0' o '\ n') y hacer 'break' fuera del ciclo después de obtenerlo. –

1

Usar try and catch sería útil. :)

Pruebe esto: Ya se ha declarado un puntero global SerialPort * pu y se ha abierto el puerto.

int rxstring(char *cstr, unsigned int len, bool print_str) 

{ 

char temp=0; 
int i=0; 
while(temp!='\n') 
{ 
    try 
    { 
     temp=pu->ReadByte(100); 
    } 
    catch(SerialPort::ReadTimeout &e) 
    { 
     //cout<<"Read Timeout"<<endl; 
     return 1; 
    } 
    if((temp!='\n')&&(temp!=0)&&(temp!=' ')) 
    { 
     cstr[i]=temp; 
     ++i; 
     //cout<<i++<<temp<<'x'<<endl; 
    } 
} 
cstr[i]='\0'; 
if(print_str) 
    puts(cstr); 
return 0; 
} 

Referencia: http://libserial.sourceforge.net/doxygen/class_serial_port.html#a15

Cuestiones relacionadas