Чтение с Arduino tty с помощью FILE * - PullRequest
1 голос
/ 02 сентября 2011

Насколько я вижу, одним из лучших источников для выяснения того, как читать и писать в узел /dev/serial/by-id/*arduino* dev, является эта ссылка:

http://todbot.com/blog/2006/12/06/arduino-serial-c-code-to-talk-to-arduino/

Однако его serialport_read_until пахнет подозрительно. Разве serialport_read_until(fd, buf, '\n') не совпадает с fgets(buf, bufsize, fptr)? Другими словами, что мешает мне использовать fdopen в дескрипторе файла для получения FILE *fptr, а затем использовать fgets / fscanf / fgetc?

Я пробовал этот подход. Пишущие вызовы, такие как fputc, работают, но вызовы чтения перестают работать с errno = 0.

Код инициализации:

devfd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
int devfl = fcntl(devfd, F_GETFL);

// Serial/terminal options
termios termopts;
if (tcgetattr(devfd, &termopts))
    throw;

// No parity; No flow control; One stop bit
// Select 8 data bits
// local ownership; read enabled
termopts.c_cflag = CS8 | CLOCAL | CREAD;
// No canonical features; raw mode; no echo
termopts.c_lflag = 0;
// No input processing features; raw mode
termopts.c_iflag = 0;
// No output processing features; raw mode
termopts.c_oflag = 0;

if (cfsetispeed(&termopts, B115200)) // 115200 baud in
    throw;
if (cfsetospeed(&termopts, B115200)) // 115200 baud out
    throw;

// Read timeout
termopts.c_cc[VTIME] = 10; // Time out after 1s
termopts.c_cc[VMIN] = 0;   // Wait for each character

if (tcsetattr(devfd, TCSANOW, &termopts))
    throw;

devf = fdopen(devfd, "r+");
if (!devf)
    throw;

Функции записи и чтения:

void dputc(char comm)
{
    if (fputc(comm, devf) == EOF)
        throw;
    if (fflush(devf))
        throw;
}

void dputs(const char *str)
{
    if (fputs(str, devf) < 0)
        throw;
    if (fflush(devf))
        throw;
}

void dprintf(const char *str...)
{
    va_list ap;
    va_start(ap, str);
    int n = vfprintf(devf, str, ap);
    va_end(ap);
    if (n < 1)
        throw;
    if (fflush(devf))
        throw;
}

Код чтения:

unsigned short f;
if (fscanf(devf, "%hu", &f) < 1)
    throw;

Есть идеи, почему такое чтение не удастся?

Спасибо.

Ответы [ 2 ]

1 голос
/ 06 сентября 2011

Поскольку в Arduino используется чип FTDI, вы также можете использовать libftdi .Это значительно упрощает настройку скорости передачи и других функций.

Большинство дистрибутивов Linux имеют libftdi в своих репозиториях.

1 голос
/ 06 сентября 2011

Я решил это. Было много проблем:

  • В OpenSuse 11.2 группа для /var/lock неверна. Он установлен на root, когда должно быть lock.
  • Я не входил ни в группы lock, ни dialout.
  • Arduino автоматически перезагружается каждый раз, когда драйвер, стоящий за /dev/ttyACM*, видит новый дескриптор файла. Это Arduino Uno занимает довольно много времени после того, как дескриптор открыт, чтобы быть доступным (> 1 с). Это исправлено отправкой загрузочного сообщения из Arduino и ожиданием его в клиенте Linux после открытия дескриптора файла.
  • FILE* функции работают. Тем не менее, он недоволен чтением и записью на одной и той же ручке; он облажается ищет. Мне нужно было два отдельных дескриптора и два отдельных FILE* s.
  • Мне пришлось отключить O_NONBLOCK.

Предупреждаем программистов драйвера Arduino!

...