【发布时间】:2014-05-05 06:40:55
【问题描述】:
在通过how to open, read, and write from serial port in C 中的@wallyk 回答后,我编写了一个程序来通过我的USB 端口发送数据。我需要发送一个 6 字节的数据,其中第一个字节应该是标记奇偶校验,其余的应该是空间奇偶校验。这就是我声明 2 个变量 msg1 和 msg2 的原因
#include<stdio.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include<fcntl.h>// used for opening ttys0
#include<sys/ioctl.h>
#include<sched.h>
#include<string.h> // for memset
#include<time.h>
int set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty); // initialize all in struct tty with 0
if (tcgetattr (fd, &tty) != 0)// gets parameters from fd and stores them in tty struct
{
perror("error from tcgetattr");
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars, CSIZE -> character size mask
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // ignore break signal
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;// 1 stop bit
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0) // TCSANOW -> the change takes place immediately
{
perror("error from tcsetattr");
return -1;
}
return 0;
}
int main()
{
char *portname = "/dev/ttyUSB0";
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
perror("error opening");
return;
}
char msg1[1]={0x01};
char msg2[5]={0x02,0x08,0x00,0xff,0xf5};
set_interface_attribs (fd, B115200,PARENB|PARODD|CMSPAR); // set speed to 115200, bps,mark parity
// set no blocking
write (fd, msg1, sizeof msg1);
set_interface_attribs (fd, B115200,PARENB|CMSPAR); // set speed to 115200 bps, space parity
write (fd,msg2,sizeof msg2);
close(fd);
return 0;
}
但是现在我发送的所有数据似乎都是空间奇偶校验而不是标记奇偶校验。即,如果我已将第一个字节配置为以标记奇偶校验发送,其余字节以空间奇偶校验发送,那么所有字节都以空间奇偶校验发送。现在,如果我将第一个字节配置为以空间奇偶校验发送,其余字节以标记奇偶校验发送,那么所有字节都以标记奇偶校验发送。
【问题讨论】:
-
当您调用
write时,可能不会立即写入数据,因为内核可能有自己的缓冲。如果您正在使用例如USB 转串行加密狗它也可能有自己的缓冲区。因此,您可以在发送任何数据之前第二次更改属性。 -
@ Joachim Pileborg 好吧,我什至尝试在发送第一个字节后使用 15 毫秒的延迟。输出还是一样的
-
在写完
msg1之后尝试调用tcdrain(fd);。 -
tcdrain(fd) 也没有提供所需的 o/p,但如果我创建 25 毫秒或以上的延迟,我将正确获得 o/p。感谢您的帮助
-
尝试在第一个字节后关闭端口,然后再次重新打开并在发送其余部分之前调整设置。
标签: c linux serial-port