10

所以我有这个测试代码通过 USB 串行端口发送“HELLO”:

int fd;
struct termios tty;

if((fd = open("/dev/ttyUSB0", O_WRONLY|O_NONBLOCK|O_NOCTTY)) == -1){
err(1, "Cannot open write on /dev/ttyUSB0");
}

tcgetattr(fd, &tty);
tty.c_iflag = 0;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = 0;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 0;
cfsetospeed(&tty, B19200);
cfsetispeed(&tty, B19200);
tty.c_cflag |= CREAD|CRTSCTS|HUPCL|CS8;
tcsetattr(fd, TCSANOW, &tty);

printf("Write: %i\n", write(fd, "HELLO", 5));

sleep(5);

if(close(fd) != 0){
warn("Could not close write fd");
}

程序执行良好,并发送“HELLO”,但有一个问题。调用 write() 函数时似乎不会发送“HELLO”,而是在关闭文件描述符时发送。我在上面添加了 sleep(5) 行来测试这个理论,果然,“HELLO”在程序执行后约 5 秒发送。如何在 write() 命令之后而不是在 close() 之后立即发送“HELLO”?

4

8 回答 8

8

该设备是 tty 设备,因此 fsync 无济于事,也许 fflush 也无济于事。

默认情况下,设备在规范模式下工作,这意味着数据被打包成行单位。您可能会发现在数据中添加 cr/lf 对会导致数据被发送。

您需要确保规范模式已关闭。此外,R 的答案将很有用。

http://en.wikibooks.org/wiki/Serial_Programming/termios

于 2010-07-12T14:21:45.613 回答
6

从手册页write()

write() 的成功返回并不能保证数据已提交到磁盘。事实上,在一些有缺陷的实现中,它甚至不能保证已成功为数据保留空间。唯一可以确定的方法是在完成所有数据的写入后调用 fsync(2)。

您需要调用fsync()文件描述符以确保实际提交数据。

于 2010-07-12T12:58:56.103 回答
3

首先,不知道为什么您首先将所有 termios 字段设置为 0,然后在不对其前面的 0 进行任何修改的情况下,决定在 cflag 上设置通常的 rs232 标志。(而不是直接在没有 OR 的情况下这样做,您现在将其设置为 0,上面)。

您可能喜欢的 - 而不是设置所有这些标志只是 cfmakeraw() termios 字段。

还有,同步();没有任何参数(不是 fsync!;)似乎将所有挂起的输出发送到所有文件描述符,而不仅仅是块设备。还有tcp套接字和rs232 ..

并且 open() 有一个选项 O_SYNC (O_SYNC 和 O_ASYNC 的名称令人困惑,但与串行线路协议是否有时钟无关,一个立即提交 write(),另一个在输入时生成一个用于捕获的信号变得可用(有点像 dos 上基于 irq 的 rs232 ;)

在 open() 中设置 O_SYNC 可能已经解决了您的问题。

也'通过读取另一端的数据'......有这些东西叫做'leds'和'电阻器',你可以连接到TXD并查看数据;)还有一些东西叫做'rs232分线盒'或一个可以使其直接可见的范围;)这种方式比“猜测”哪一方行为不正确要容易得多。

警告:未测试代码。它编译。但我所有的 ttyUSB0 电缆都在另一栋楼里。但我认为你的主要问题是O_SYNC。将所有 termios 废话设置为 0 与 cfmakeraw() 几乎相同......如果你要打开它,为什么要设置 CREAD 只写?(为什么要打开它只写而不是读写? - 而且只写你不必害怕它成为一个控制 tty (O_NOCTTY ;) 所以在只写的情况下,这也不是完全需要的.. .

刚刚注意到 %i (与 %d btw 相同)格式化程序也触发类型不匹配警告 write() 的 ssize_t 返回值,因此将其转换为 (int)

#include<termios.h>
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

void main(){
int fd;
struct termios tty;
fd=-1;
while(fd<0){fd=open("/dev/ttyUSB0",O_WRONLY|O_NONBLOCK|O_NOCTTY|O_SYNC);sleep(1);};
cfmakeraw(&tty);
tty.c_cflag=CREAD|CRTSCTS|HUPCL|CS8;
cfsetospeed(&tty,B19200);
cfsetispeed(&tty,B19200);
tcsetattr(fd,TCSANOW,&tty);
printf("Write: %i\n",(int)write(fd,"HELLO",5));
sync();//if all else fails, also try without, O_SYNC should already fix that.
close(fd);
};
于 2016-02-02T21:47:16.613 回答
2

输出端口通常是缓冲的,因此在您写入输出流与实际发送到磁盘、线路或其他内容的内容之间存在或多或少的差距。这通常是为了提高效率。

请参阅 fflush(3) 以强制将缓冲区提交到输出。

您可能还可以以一种非缓冲的方式打开输出描述符,但使用fflush说“就是这样,我完成了”可能会更好。

于 2010-07-12T13:02:37.483 回答
0

更改此行:

tty.c_cc[VMIN] = 0;

对此:

tty.c_cc[VMIN] = 1;
于 2010-07-12T13:50:10.790 回答
-1

缓冲区没有被刷新。冲洗。

于 2010-07-12T12:58:46.060 回答
-1

请看这个问题。基本上,您需要刷新文件才能在需要时进行 IO。

于 2010-07-12T12:59:03.310 回答
-1

尝试做一个

fflush( NULL );

之后write()。也许有一些内部缓冲区没有被刷新。

于 2010-07-12T12:59:54.150 回答