【问题标题】:Serial communication of XBee on Linux COM using C使用 C 在 Linux COM 上的 XBee 串行通信
【发布时间】:2015-10-31 09:44:50
【问题描述】:

我已将我的 XBee 模块(通过 UART 进行通信)连接到我的 PC。我已经从一个遥远的节点将数据无线传输到我的 XBee。

我在我的 Linux 终端上接收字节时出现问题。虽然我能够将数据传输到远程节点。找到我在我的 Linux 终端上编写的以下代码以进行串行通信。但为了调试,我将 XBee 配置为环回。(TXD-RXD 短路)

#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 */

//Initialize serial port
int initport(int fd)
{
    int portstatus = 0;

    struct termios options;

    // Get the current options for the port...
    tcgetattr(fd, &options);

    // Set the baud rates to 9600...
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);

    // Enable the receiver and set local mode...
    options.c_cflag |= (CLOCAL | CREAD);

    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    //options.c_cflag |= SerialDataBitsInterp(8);     /* CS8 - Selects 8 data bits */
    options.c_cflag &= ~CRTSCTS;                      // Disable hardware flow control
    options.c_iflag &= ~(IXON | IXOFF | IXANY);       // Disable XON XOFF (for transmit and receive)
    //options.c_cflag |= CRTSCTS;                     /* Enable hardware flow control */

    options.c_cc[VMIN] = 1;   //Minimum characters to be read
    options.c_cc[VTIME] = 2;    //Time to wait for data (tenths of seconds)
options.c_oflag &=~OPOST;
options.c_iflag &=~(ICANON | ECHO | ECHOE | ISIG);
    // Set the new options for the port...
    tcsetattr(fd, TCSANOW, &options);

    //Set the new options for the port...
    tcflush(fd, TCIFLUSH);
    if (tcsetattr(fd, TCSANOW, &options) == -1)
    {
        perror("On tcsetattr:");
        portstatus = -1;
    }
    else
        portstatus = 1;

    return (portstatus);
}

int open_port(void)
{
    int fd; /* File descriptor for the port */
    fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NONBLOCK);

    if (fd == -1)
    {
        /*      Could not open the port.        */
        perror("Open_port: Unable to open /dev/ttyUSB0 --- \n");
    }
    else
{message print....};

    return (fd);
}

int main(void)
{
    int i;
    unsigned char write_buf[] =
        {0x7E, 0x00, 0x16, 0x10, 0x01, 0x00, 0x13,
         0xA2, 0x00, 0x40, 0xE4, 0x22, 0x64, 0xFF,
         0xFE, 0x00, 0x00, 0x41, 0x42, 0x43, 0x44,
         0x41, 0x42, 0x43, 0x43, 0x7F};

    int serial_fd = open_port();

    if (serial_fd == -1)
        printf("Error opening serial port /dev/ttyUSB0 \n");
    else
    {
        printf("Serial Port /dev/ttyUSB0 is Open\n");
        if (initport(serial_fd) == -1)
        {
            printf("Error Initializing port");
            close(serial_fd);
            return 0;
        }
        int n = write(serial_fd, &write_buf, sizeof write_buf);
        if (n < 0)
            fputs("write() failed!\n", stderr);
        else
        {
            printf("Successfully wrote %d bytes\n", sizeof write_buf);
            for (i=0; i<n; i++)
            {
                printf("%c ",write_buf[i]);
            }
        }
    }
usleep(200000);
     char read_buf[128];
     int n1 = read(serial_fd, read_buf, sizeof read_buf);

     // sleep(1);

     if (n1 < 0)
         fputs("Read failed!\n", stderr);
     else
     {
         printf("Successfully read from serial port -- %s\n With %d Bytes", read_buf,n1);
     }

     // sleep(.5);
     // usleep(500000);

     printf("\n\nNow closing serial port /dev/ttyUSB0 \n\n");
     close(serial_fd);

     return 0;
}

当我执行此代码时,它确实显示收到了 1 个字节。我在 read() 之前引入了延迟。但它显示在 Tera Term(某种超级终端)上。此外,我必须在 Xbee 上发送/接收十六进制字符串才能传输,因为它们以 API 模式进行通信。

我该如何解决这个问题?

【问题讨论】:

  • 这是一个写得很好的问题。我希望我们有更多这样的东西。
  • 您是否与程序同时运行 Tera Term?
  • @sawdust 你能解释一下cfmakeraw() 会做什么吗?
  • @PeterMortensen 是的。我的测试设置作为一个模块连接在 linux 上,另一个模块连接在 Windows 上与 Teraterm。当我从连接的 linux 发送时,Teraterm 已收到流。但反之亦然。
  • @sawdust 在接收器处等待接收流不是更合适吗?因为字节流随时都会到来。

标签: c linux api serial-port xbee


【解决方案1】:

您没有等待足够长的时间来接收来自 XBee 模块的字节。尝试将您的sleep(1) 移动到read() 之前,并可能将其增加到几秒钟。在您尝试调用 read!请记住,write() 正在将数据传递给操作系统,并通过串行连接进行缓冲。

在典型的应用程序中,您会有一个循环,您会定期尝试read(),然后处理从远程端传入的任何内容。请记住,您会以块的形式看到它,并且不能仅将其打印为字符串。您经常会在字符串上缺少空终止符,如果您有二进制数据,它可能会导致您的终端会话出现乱码。

当您使用它时,请考虑将您的 XBee 模块配置为 115,200bps 而不是 9600。它的响应速度会更快。

您可能想看看这个Open Source ANSI C XBee Host Library 我已经投入了很多工作。它可以针对 POSIX 系统,包括许多层,用于从原始串行到 API 模式,甚至一些 ZigBee 处理(ZDP 端点和 ZCL)的通信。

【讨论】:

  • "尝试将 sleep(1) 移到 read() 之前" -- 无用的建议,因为 read() 无论如何都会阻塞,因此前面的 sleep() 将是多余的。
  • @sawdust: 串口不会是非阻塞打开的吧?因此 read() 将返回 -1 并将 errno 设置为 EAGAIN 如果没有任何可用的字节。
  • 如果你的断言是真的,那么为什么 OP 不报告你描述的那个场景呢? OP 没有报告 “读取失败!” 消息出现。相反,OP 报告没有发生任何事情,即 “它没有显示任何字节”。这与未返回的阻塞读取一致。所以是的,端口是非阻塞打开的。但是查看代码也发现有fcntl(fd, F_SETFL, 0)成功打开后恢复阻塞模式。
  • @tomlogic 我在拨打read() 之前介绍了usleep()。现在经过一些修改后,我发布了新代码。现在我只收到单字节。会是什么原因?
  • @abhi1610,第一个进来的字符读取成功。你需要继续调用read()来获取剩余的字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 2014-04-12
  • 1970-01-01
相关资源
最近更新 更多