【发布时间】:2016-12-28 19:06:36
【问题描述】:
我在设备模式下使用 Raspberry Pi Zero,在主机模式下使用 Raspberry Pi B。我用 USB 数据线将两者连接起来。我现在的目标只是在两个 Pi 之间来回发送简单的任意数据。
问题是,无论 Pi 先写入串行端口,最终都会读取它写入的内容。我编写的程序让设备发送d\n,主机发送h\n。因此,如果设备先写入,则主机正确读取d\n,然后将h\n 写入串行端口。但设备最终读取d\n!如果我切换它以便主机先写入,问题仍然存在。
我尝试在写入之后但在读取之前向程序添加各种tcflush 调用,但它不起作用。我也试过睡不同的时间。我已经阅读了为每个写入的字符等待 100 微秒,并且我已经睡了几秒钟。
由于 Pi Zero 的单个支持数据的 USB 端口,我的设置要求我不能同时在两个 Pi 之间建立持续连接。所以,为了测试,我实际上是插入键盘并运行程序,然后插入正确的电缆来传输数据。我可以传输数据,但不能在写入后传输,因为程序只是读回它写入的内容。
我开始认为我掉进了一个我无法理解的菜鸟陷阱。这是我正在使用的代码:
#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编译来触发它。 -
哦,我明白了,如代码中所述。但我不喜欢它——会导致手指麻烦。我建议必须定义一个特定值,否则编译将失败。
-
尝试添加
tty.c_lflag &= ~ECHO; -
@MarkPlotnick 没有成功。仍在读取写入的数据。
标签: c serial-port usb