Linux последовательный порт чтения () неверные данные - PullRequest
2 голосов
/ 08 ноября 2011

Я пишу небольшую программу для связи с AVR MCU, на стороне ПК я использовал posix write () и read () для доступа к последовательному порту, я подключил контакты RX и TX последовательного порта, чтобы проверить, может ли он работать правильноотправка и получение данных, теоретически все отправляемое должно в конечном итоге быть одинаковым в приемном буфере, это тот случай, когда отправляемое сообщение короткое, а частота отправки низкая, read () возвращает то же сообщение, что и отправленное, нокогда сообщение становится длиннее и отправляется чаще, read () возвращает неправильные данные, символы, кажется, находятся в неправильном порядке, я думаю, read () или write () не в режиме блокировки, поэтому, когда старая передача не прошлаt еще не закончен, новая передача (write ()?) прибыла, прерывает старую передачу и изменяет буфер TX.

Я новичок в программировании Linux, пожалуйста, кто-нибудь, помогите мне в этом, это убивает меня ... любая помощь очень ценится.

Редактировать: я заметил на man-странице write (): Успешный возврат из write () не дает никаких гарантий того, что данные были записаны на диск.Фактически, в некоторых ошибочных реализациях это даже не гарантирует, что пространство было успешно зарезервировано для данных.Единственный способ убедиться в этом - вызвать fsync (2) после того, как вы закончите записывать все свои данные.

Я попробовал функцию fsync (), но получаю тот же неправильный результат.

Вот код:

#include <stdio.h>
#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 */

int main(void) {

    int fd;
//  fd = open("/dev/tty.usbmodem1a21", O_RDWR | O_NOCTTY | O_NDELAY);
    fd = open("/dev/tty.usbmodem1a21", O_RDWR | O_NOCTTY);
    if (fd == -1) {
        //Could not open the port.
        perror("open_port: Unable to open port ");
    }
        else
        fcntl(fd, F_SETFL, 0);

    char s[] = "Hello, this is a test of the serial port access";

    int cnt;
    unsigned char in[100];
    for(cnt=0; cnt<10; cnt++) {
        int n = write(fd, s, sizeof(s));
        if (n < 0)
            fputs("write() failed!\n", stderr);

        usleep(50000);  // works fine with delay

        read(fd, in, 100);


            printf("%s\n", in);
    }

    return 0;
}

with sleep() between write() and read() without sleep() between write() and read()

Эрик

Ответы [ 2 ]

2 голосов
/ 08 ноября 2011

(1) Всегда проверяйте коды возврата.(2) Если вы попытаетесь напечатать строку, которая не была завершена нулем, вы в конечном итоге напечатаете любой мусор, который находится в памяти (или хуже).

Я предполагаю, что ваша реальная проблема заключается в том, чточтение / запись НЕ гарантирует запись указанного вами количества байтов.Число, которое они фактически читают / пишут, находится в коде возврата.Таким образом, по мере заполнения буфера fd вы можете написать 1 байт, а затем попытаться напечатать ненулевую строку из этого 1 байта и всего после него.

Попробуйте что-то подобное и посмотрите, изменится ли что-либо.

int cnt;
unsigned char in[100];

for(cnt=0; cnt<10; cnt++) 
{
    int n = write(fd, s, sizeof(s));

    if (n < 0)
    {
        perror("write");
        exit(EXIT_FAILURE);
    }

    n = read(fd, in, 100);

    if (n < 0)
    {
        perror("read");
        exit(EXIT_FAILURE);
    }

    in[n] = '\0';

    printf("%s\n", in);
}
2 голосов
/ 08 ноября 2011

Начните с использования возвращаемого значения из read (). Помните: чтение не приводит к выводу нулевых строк.

n=read(fd, in, 100);

        printf("%*.*s\n", n,n, in);
...