2012-01-28 16 views
5

Sto usando LibSerial su Ubuntu per leggere e scrivere dati sulla porta seriale.Lettura e scrittura su porta seriale in Ubuntu con C/C++ e LibSerial

Al momento, sono in grado di scrivere e ricevere stringhe sulla porta seriale, ma il mio codice non funziona molto bene: in particolare, Mi piacerebbe controllare la funzione di lettura per poter leggere solo se c'è qualcosa da leggere e uscire quando non ci sono informazioni da leggere per inviare un altro comando senza riempire il programma di flusso.

che voglio fare:

  • Scrivi un comando
  • attendere la risposta
  • poi scrivere un altro comando
  • attendere la risposta

Ora, io sono in grado per inviare il primo comando e leggere la risposta usando la funzione di lettura in un ciclo while, ma non sono in grado di fare nient'altro. Non riesco a inviare il secondo comando perché il ciclo while non si chiude mai, quindi il programma continua a leggere.

Potete aiutarmi, per favore?

Questo è il codice che sto usando: (Leggere e scrivere sono funzione alla fine del codice)

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

risposta

4

Credo non vi resta che utilizzare while(serial_port.rdbuf()->in_avail() > 0) come condizione per il vostro ultimo ciclo while . Quindi leggerà tutti i dati disponibili ("risposta") e dopo potrai inviare il secondo comando.

+0

Il problema è che se io uso ** serial_port.rdbuf() -> in_avail()> 0 ** esso non entra mai nel ciclo while. Sembra molto strano, perché ci sono dati sulla porta seriale ma il programma non li legge. Al contrario, se uso ** while (1) ** lo legge correttamente. –

+0

Bene, quale personaggio ottieni dopo aver letto tutti i byte della risposta effettiva? Puoi controllare quel personaggio (penso che dovrebbe essere '\ 0' o '\ n') e fare 'break' fuori dal giro dopo averlo capito. –

1

Utilizzare try and catch sarebbe utile. :)

Prova questo: Un puntatore globale SerialPort * pu è già stato dichiarato e la porta è stata aperta.

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; 
} 

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