Несоответствие чтения из последовательного порта в C LINUX - PullRequest
0 голосов
/ 29 января 2019

У меня проблема несогласованности при чтении через последовательный порт с использованием Linux и C.

Код, который я использую для настройки последовательного порта, выглядит следующим образом:

serial = open("/dev/ttymxc1", O_RDWR | O_NOCTTY | O_SYNC);      //Open in non blocking read/write mode
    if (serial == -1)
    {
        //ERROR - CAN'T OPEN SERIAL PORT
        printf("Error - Unable to open UART.  Ensure it is not in use by another application\n");
    }

    struct termios tty;
    memset (&tty, 0, sizeof tty);
    if (tcgetattr (serial, &tty) != 0)
    {
        printf("error from tcgetattr");
        return -1;
    }

    cfsetospeed (&tty, B115200);

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
    // disable IGNBRK for mismatched speed tests; otherwise receive break
    // as \000 chars
    //tty.c_iflag &= ~IGNBRK;         // disable break processing
    tty.c_lflag = 0;                // no signaling chars, no echo,
                                            // no canonical processing
    tty.c_oflag = 0;                // no remapping, no delays
    tty.c_cc[VMIN]  = 0;            // read doesn't block
    tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

    tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                            // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
    tty.c_cflag |= 0;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr (serial, TCSANOW, &tty) != 0)
    {
        printf("error from tcsetattr");
        return -1;
    }

Затем яопросить UART (из того же потока, который настроил последовательный порт) с помощью следующего кода:

while(1)
{
    if (serial != -1)
    {
        //memset(rx, 0, sizeof(rx));
        int rx_length = read(serial, &rx, MAX_TXRX_BUF);        //Filestream, buffer to store in, number of bytes to read (max)
        if(rx_length > 0){
            //Bytes received
            //rx[rx_length] = '\0';

            printf("1) %i bytes read : %s\n", rx_length, rx);
            //forward_data(rx, rx_length);
            printf("2) %i bytes read : %s\n", rx_length, rx);
            //tcflush(serial, TCIOFLUSH);
        }
        // else: NO DATA
    }
    else{
        fprintf(stderr, "TEST: %s SERIAL FAIL\n", __func__);
        releaseUart();
    }

}

Проблема заключается в том, что этот вывод:

printf("1) %i bytes read : %s\n", rx_length, rx);

всегда работает и печатаетправильные данные, прочитанные из серийного номера.В то время как вторая печать:

printf("2) %i bytes read : %s\n", rx_length, rx);

, которая находится непосредственно под первой, иногда работает и другие элементы, она просто печатает неизвестный символ.

Ниже я покажу вам вывод, но в случаев котором он работает и в случае, когда он не работает:

Правильно:

1) 2 bytes read : gv
2) 2 bytes read gv

Неправильно:

1) 2 bytes read : gv
2) 2 bytes read: �

Почему даже если два отпечаткаодна под другой, иногда я получаю такие несоответствия при печати одного и того же буфера?

Заранее большое спасибо за вашу помощь.

С наилучшими пожеланиями, Марко

1 Ответ

0 голосов
/ 29 января 2019

Я не могу объяснить, почему выходной сигнал изменяется между первым printf и вторым.Однако read не завершает NUL свой буфер, что означает, что после того, как вы

int rx_length = read(serial, &rx, MAX_TXRX_BUF);

сделаете, не имеет действительную строку C в rx.Вместо этого вам нужно сделать что-то вроде этого:

char rx[MAX_TXRX_BUF + 1]; // extra space for terminator
ssize_t rx_length = read(serial, rx, MAX_TXRX_BUF);
if (rx_length >= 0) {
    rx[rx_length] = '\0';
    // use rx here
    // if rx_length == 0, handle EOF
} else {
    // read error
}

Несмотря на то, что я не знаю, почему выходные данные меняются, я предсказываю, что если вы поместите ваши два оператора printf туда, где у меня есть // use rx here, онивсегда печатает одно и то же.

Примечание: взятие адреса всего массива, как вы это делали с &rx, почти всегда является ошибкой.В большинстве случаев, что вы действительно хотите, чтобы обратиться к массиву в C, это адрес первого элемента, который вы получаете только с rx.(По причинам, которые слишком утомительны и касательны для понимания, read не волнует, какой из двух вы предоставляете, но в других случаях это может привести к незначительным ошибкам. Поэтому в C лучше всего использовать адреспервого элемента даже в тех случаях, когда это не имеет значения, зарезервируйте &rx для тех редких случаев, когда вам конкретно нужен адрес всего массива.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...