Question

I have problems reading data from ttyUSB0 using C++. I have an own thread reading data in blocking mode from ttyUSB0. When I read only single characters the data arrives in fixed blocks(not nice bot ok). That could be some internal buffer from the FTDI chip on my USB to UART converter. But if try to read more than a singe character, I only receive zero blocks. There are no errors on the read or init commands. Does anybody have an idea how to solve this problem.

Send: dfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfsfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf

Receive:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Here is my code.

void BoardCommunicator::execute()
{
    connection.openCon();
    uint8_t buffer[16] = {0};
    while(true)
    {
    //  unsigned char b = connection.readByte();
        if(connection.readBlock(buffer,16) == 0)
            std::cout << "EOF" << std::endl;
        else
            for(uint32_t i = 0; i < 16; i++)
                std::cout << (int)buffer[i] << " ";
        std::cout << std::endl;
    }
}

void SerialConnection::openCon()  throw (SerialPortOpenException&)
{
    conHandler = open(udevFileName , O_RDWR | O_NOCTTY);// | O_NDELAY | O_NONBLOCK);
    if (conHandler < 0) 
        throw SerialPortOpenException("Can not open given comport");

    cfsetispeed(&port_settings, B2000000);    // set baud rates
    port_settings.c_cflag = B2000000 | CS8 | CREAD | CLOCAL;
    port_settings.c_iflag = IGNPAR;
    port_settings.c_oflag = 0;
    port_settings.c_lflag = 0;
    if(tcsetattr(conHandler, TCSANOW, &port_settings) < 0)
        throw SerialPortOpenException("Was not able to aply settings to serail link.");// apply the settings to the port
}
//Does not work at all. Receives only zeros! Why? 
int SerialConnection::readBlock(uint8_t* buffer, uint32_t size)
{
    if(buffer == NULL)
        throw IllegalArgumentException("Can not read a block to null buffer");

    for(uint32_t index = 0; index < size; index++)
        buffer[index] = 0;
    int result;
    do{
        result = read(conHandler, &buffer, size);
    } while (errno == EINTR );
    if(result < 0)
        throw ReadBlockException("Can not read from serial link.");
        return result;
}
//Works only in blocking mode and data arrives in fixed sized blocks
uint8_t SerialConnection::readByte() const throw (ReadByteException&)
{
    int result = 0;
    uint8_t data = 0;
    do //Check if read waked up by any signal
    {
        result = read(conHandler, &data, 1);
    } while (errno == EINTR || errno == 11);
    std::cout << errno <<std::endl;
    if(result < 0)
        throw ReadByteException("Can not read from serial link.");
    return data;
}

Would be nice if somebody have already some experience with this stuff. Thanks

Was it helpful?

Solution

You have two bugs.

First, this code:

    result = read(conHandler, &buffer, size);

You read into the place where the address of buffer is stored rather than the buffer itself.

Second, you throw the results of read away, so you have no idea how many bytes you read. If the code is intended to read exactly size bytes, you need to do something like this:

    int total_read = 0;
    do
    {
        result = read(conHandle, buffer + total_read, size - total_read);
        if (result <= 0) return result;
        total_read += result;
    }
    while (total_read < result);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top