Я использую малиновый Pi Zero в режиме устройства и малиновый Pi B в режиме хоста. Я подключаю два кабеля USB. Моя цель прямо сейчас - просто отправить простые, произвольные данные назад и вперед между двумя Pi.чтение из последовательного порта всегда возвращает то, что было написано
Проблема в том, что Pi пишет в последовательный порт, сначала заканчивает чтение того, что он написал. Программа, которую я написал, отправляет устройство d\n
, а хост отправляет h\n
. Итак, если устройство записывает сначала, хост правильно считывает d\n
, а затем записывает h\n
в последовательный порт. Но устройство заканчивается чтением d\n
! Проблема сохраняется, если я переключу его так, чтобы хост сначала записывал.
Я попытался добавить различные tcflush
звонки в программу после записи, но перед чтением, но это не сработает. Я также пробовал спать в течение некоторого времени. Я читал, ожидая 100 микросекунд за каждый написанный персонаж, и я спал несколько секунд.
Моя установка требует, чтобы у меня не было постоянной связи между обоими Pi в то же время из-за единственного порта USB с поддержкой данных Pi Zero. Итак, чтобы проверить, я фактически подключаю клавиатуру и запускаю программу, а затем подключаю соответствующий кабель для передачи данных. Я могу передавать данные, но не после записи, потому что программа просто читает, что она написала.
Я начинаю думать, что попал в ловушку noob, которую я не могу понять. Вот код, я использую:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
/*
* gcc -o device_rw -DDEVICE serial_rw.c
* gcc -o host_rw serial_rw.c
*/
#define SERIAL_DEVICE "/dev/ttyGS0"
#define SERIAL_HOST "/dev/ttyACM0"
#ifdef DEVICE
#define _TTY SERIAL_DEVICE
#else
#define _TTY SERIAL_HOST
#endif
int
set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_iflag |= IGNPAR | IGNCR;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_iflag |= ICANON;
tty.c_iflag &= ~OPOST;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
void
write_serial (int fd, const char *buf, int len)
{
printf("WRITE: %s\n", buf);
write(fd, buf, len);
}
void
read_serial (int fd, char *buf, int len)
{
ssize_t nread = read(fd, buf, len);
if (nread > 0 && nread <= len) {
buf[nread] = 0;
printf(" READ: %s\n", buf);
}
}
int
main (int argc, char **argv)
{
char buf[80];
int fd = open(_TTY, O_RDWR | O_NOCTTY);
if (fd < 0) {
fprintf(stderr, "Can't open %s: %s\n", _TTY, strerror(errno));
goto exit;
}
if (set_interface_attribs(fd, B115200) < 0) {
goto exit;
}
#ifdef DEVICE
printf("device: %s\n", _TTY);
write_serial(fd, "d\n", 2);
usleep((2 + 25) * 100);
read_serial(fd, buf, 2);
#else
printf("host: %s\n", _TTY);
read_serial(fd, buf, 2);
//usleep((2 + 25) * 100);
write_serial(fd, "h\n", 2);
#endif
close(fd);
exit:
return 0;
}
Где вы положили '#define DEVICE', чтобы удовлетворить ваши версии компиляции, управляемые' #ifdef DEVICE'? –
Я скомпилирую с '-DDEVICE', чтобы вызвать его. – Leroy
О, я вижу, как прокомментировано в коде. Но мне это не нравится - может привести к неприятностям с пальцами. Я предлагаю, чтобы * конкретное значение * должно быть определено, чтобы компиляция завершилась без него. –