Pocketbeagle 串行端口与霍尼韦尔 HPMA115S0 的通信问题

Pocketbeagle Serial port communication issue with Honeywell HPMA115S0

我想通过 C 程序与霍尼韦尔 HPMA115S0 传感器进行通信 运行。目标系统是 PocketBeagle 运行ning Debian。

我可以通过仅设置端口和 BPS 使用 'screen' 实用程序与传感器通信。 我还可以使用 python3 和串行库进行通信,因此我排除了任何硬件问题。

但是我不能用C程序来做。一切似乎都很好,但是当我期待收到 ACK 时,我什么也没收到。一个奇怪的方面是,如果我 运行 屏幕或 python 脚本并关闭它,那么我可以使用我的 C 程序正确通信。

我 运行 stty 检查系统启动时的差异,然后在 C 程序之后和屏幕之后,但似乎没有任何原因。我想我必须设置适当的串行掩码。现在我使用:

int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
struct termios tty;
memset(&tty, 0, sizeof tty);

if(tcgetattr(fd, &tty) != 0) {
    printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
}

tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
cfsetospeed(&tty, 9600);
cfsetispeed(&tty, 9600);
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
   printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
}

有什么帮助吗? 谢谢!

您的终端需要的是 non-canonical (a.k.a. raw) mode. The GNU libc documentation has a nice minimal example 它的设置方式。您的代码没有清除 ICANON 标志,这可能是关键标志。它应该看起来像这样:

if(tcgetattr(fd, &tty) != 0) {
    printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
}
tty.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
cfsetospeed(&tty, 9600);
cfsetispeed(&tty, 9600);
if (tcsetattr(fd, TCSAFLUSH, &tty) != 0) {
   printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
}

我 运行 Python 脚本和带有 strace 的 C 程序,我注意到问题出在:

cfsetospeed(&tty, 9600);
cfsetispeed(&tty, 9600);

它应该使用 'B9600' 而不是 '9600'。

正确的形式是:

cfsetospeed(&tty, B9600);
cfsetispeed(&tty, B9600);