【问题标题】:How do I read data from serial port in Linux using C?如何使用 C 从 Linux 中的串口读取数据?
【发布时间】:2018-12-06 03:41:14
【问题描述】:

我是使用 C 在 Linux 中进行串行编程的新手。我找到了一小段代码来在串行端口上写入数据,我在这里分享。运行此代码后,我可能会假设数据已写入特定端口。现在我想打开另一个终端并使用单独的代码来读取写入在该特定端口上的数据 - 我该怎么做?

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

/*
 * 'open_port()' - Open serial port 1.
 *
 * Returns the file descriptor on success or -1 on error.
 */
int
open_port(void)
{
  int fd; /* File descriptor for the port */

  fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1)
  {
   /* Could not open the port. */
    perror("open_port: Unable to open /dev/ttyS0 - ");
  }
  else
    fcntl(fd, F_SETFL, 0);

  n = write(fd, "ATZ\r", 4);
  if (n < 0)
    fputs("write() of 4 bytes failed!\n", stderr);

  return (fd);
}

上面的代码会将数据写入特定的端口。

【问题讨论】:

  • 请注意,write 函数可能(理论上)返回 3 表示它成功写入了 4 个字节中的 3 个。您可以决定是否将“短写入”视为错误,或者是否重试写入缓冲区的剩余部分。

标签: c linux serial-port


【解决方案1】:

理论上,你只需要打开相关端口进行读取,使用read()获取数据即可。

int
read_port(void)
{
    int fd = open("/dev/ttyS0", O_RDONLY | O_NOCTTY);
    if (fd == -1)
    {
        /* Could not open the port. */
        perror("open_port: Unable to open /dev/ttyS0 - ");
    }

    char buffer[32];
    int n = read(fd, buffer, sizeof(buffer));
    if (n < 0)
        fputs("read failed!\n", stderr);
    return (fd);
}

有区别;值得注意的是,读取需要一个缓冲区来放入数据。显示的代码丢弃了读取的第一条消息。请注意,短读取仅表示在读取完成时可用数据少于请求的数据。它不会自动指示错误。想一个命令行;一些命令可能是一两个字符 (ls),而其他命令可能非常复杂 (find /some/where -name '*.pdf' -mtime -3 -print)。使用同一个缓冲区来读取两者的事实不是问题。一个 read 给出 3 个字符(包括换行符),其他 47 个左右。

【讨论】:

  • 感谢@Jonathan您的友好回复。但是当我尝试在其他终端运行这段代码时,我收到读取失败错误,为什么当我成功在端口上写入数据时它没有读取数据使用其他终端。我实际上想像套接字一样使用环回地址在终端之间进行通信!
  • 这就是实践妨碍理论的地方。要从端口成功读取,必须有一个小工具连接到写入数据供您读取的端口。因此,您必须担心端口另一侧的硬件;它将如何对计算机写入它的数据作出反应,以及它将如何写回数据以供计算机读取。
  • 真的@Jonathan我正在接近的方式只是有Linux机器并尝试使用终端进行通信。在一个终端上试图将数据写入端口,而在另一个终端上试图读取它,同样的方式开始Linux 学习套接字编程但现在看起来我还需要一些串行电缆和两台机器。无论如何,乔纳森非常感谢你的温柔帮助!
  • 如果没有配置端口 - 波特率、转换等,在大多数情况下这不会很好地工作。
  • @ChrisStratton:嗯......是的,你可能是对的。然后,您可以快速进入许多特定于系统的代码。您肯定需要从某个地方知道什么是适当的设置才能正确使用&lt;termios.h&gt; 中的功能(至少其中某些部分不是系统特定的 - 但是如果您需要设置波特率,例如,您需要知道为您打开的串行设备设置的正确波特率是多少)。
【解决方案2】:

发布的程序对端口的状态做了很多假设。在现实世界的应用程序中,您应该明确地进行所有重要的设置。我认为POSIX下学习串口编程最好的资源是

POSIX 操作系统的串行编程指南

我在这里镜像:https://www.cmrr.umn.edu/~strupp/serial.html

【讨论】:

  • @n0rd:感谢您的提醒。我已经在我的服务器上设置了一个镜像副本。
  • @datenwolf:主页是镜像的,但所有子页面的链接似乎都死了。我可以在这里找到内容:cmrr.umn.edu/~strupp/serial.html
  • @Electron:此文档没有子页面。它只是一个很长的 HTML 文件。问题是,ToC 中的链接包含文件名serial.html,而不是简单的文档内锚点。我将 HTML 中的链接更改为此类文档内锚点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
相关资源
最近更新 更多