1

所以我在一个项目中使用两个 Xbee ZB (S2B) 将数据从一个传输到另一个。它是一个 8 个数据位、无奇偶校验、1 个停止位系统 (8N1)。

我有两个问题。

1. 由于我在笔记本电脑上与 USB 适配器的 RS232(DB9 连接器)接口连接,在 B230400 的波特率下,对fwrite/fread/fopen/fclose的系统调用会比write/read/open/close更好地使用? (我认为 fread() 将无法正常工作,因为据我所知它没有波特率配置。)

2.我有一台计算机运行一个程序(发射器程序)和另一个程序(接收器程序)。两个程序都需要能够读写,因为我希望能够从发送和接收端知道不同的信息集。

就像接收端(如果我看到字母 Q,停止并关闭端口)或发送端(等待读取端发送字母 G 开始写入并在完成写入后关闭)。

在非规范输入处理下使用( http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html )中的一些代码,我尝试设置一个用于从 USB 端口写入和读取的基本模板任何一边。我的问题是:

*如果并且是否需要对发送和接收程序的 termios 结构 (newtio) 进行不同的配置设置(c_cflag、c_iflag、c_oflag、c_lflag)?*

我的代码:

#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>

int open_port(char *path, int modes)
{
    int fd; // File descriptor for port

    fd = open(path, modes); // Open the path
    if(fd == -1) return -1; // Could not be opened

    printf("Port %s opened successfully.\n", path);
    return fd; // Return fd
}

int setBaud(struct termios *termios_p, int baud)
{
    int ires = 0; int ores = 0;
    switch(baud)
    {
        0:
            ires = cfsetispeed(&termios_p, B0);
            ores = cfsetispeed(&termios_p, B0);
            break;
        50:
            ires = cfsetispeed(&termios_p, B50);
            ores = cfsetispeed(&termios_p, B50);
            break;
        75:
            ires = cfsetispeed(&termios_p, B75);
            ores = cfsetispeed(&termios_p, B75);
            break;
        110:
            ires = cfsetispeed(&termios_p, B110);
            ores = cfsetispeed(&termios_p, B110);
            break;
        134:
            ires = cfsetispeed(&termios_p, B134);
            ores = cfsetispeed(&termios_p, B134);
            break;
        150:
            ires = cfsetispeed(&termios_p, B150);
            ores = cfsetispeed(&termios_p, B150);
            break;
        200:
            ires = cfsetispeed(&termios_p, B200);
            ores = cfsetispeed(&termios_p, B200);
            break;
        300:
            ires = cfsetispeed(&termios_p, B300);
            ores = cfsetispeed(&termios_p, B300);
            break;
        600:
            ires = cfsetispeed(&termios_p, B600);
            ores = cfsetispeed(&termios_p, B600);
            break;
        1200:
            ires = cfsetispeed(&termios_p, B1200);
            ores = cfsetispeed(&termios_p, B1200);
            break;
        1800:
            ires = cfsetispeed(&termios_p, B1800);
            ores = cfsetispeed(&termios_p, B1800);
            break;
        2400:
            ires = cfsetispeed(&termios_p, B2400);
            ores = cfsetispeed(&termios_p, B2400);
            break;
        4800:
            ires = cfsetispeed(&termios_p, B4800);
            ores = cfsetispeed(&termios_p, B4800);
            break;
        9600:
            ires = cfsetispeed(&termios_p, B9600);
            ores = cfsetispeed(&termios_p, B9600);
            break;
        19200:
            ires = cfsetispeed(&termios_p, B19200);
            ores = cfsetispeed(&termios_p, B19200);
            break;
        38400:
            ires = cfsetispeed(&termios_p, B38400);
            ores = cfsetispeed(&termios_p, B38400);
            break;
        57600:
            ires = cfsetispeed(&termios_p, B57600);
            ores = cfsetispeed(&termios_p, B57600);
            break;
        115200:
            ires = cfsetispeed(&termios_p, B115200);
            ores = cfsetispeed(&termios_p, B115200);
            break;
        230400:
            ires = cfsetispeed(&termios_p, B230400);
            ores = cfsetispeed(&termios_p, B230400);
            break;
        default:
            ires = cfsetispeed(&termios_p, B9600);
            ores = cfsetispeed(&termios_p, B9600);
            break;
    }

    if(ires == -1 | ores == -1) return -1; // ISpeed or OSpeed could not be set
    else { printf("Baud set successfully to %d\n", baud); return 0; }
}

char* readIt(int fd)
{
    char buf;
    char *tmp;
    tmp = calloc(2, sizeof(char);

    if( read(fd, buf, 1) == 1 ) { tmp[0] = buf; tmp[1] = 0; } // Return char in tmp[0]
    else { tmp[0] = 0x45; tmp[1] = 0x52; } // Return ER in char meaning error
    return tmp;
}

int writeIt(int fd, char *str, int bytes)
{
    if( write(fd, str, bytes) == bytes ) return 0; // Write success
    else return -1; // Failed write
}

int main (int argc, char **argv)
{
    int usb;
    volatile int STOP = 0;

    if(argc == 1) { printf("Must enter usb port path.\n"); exit(EXIT_FAILURE); } // No second argument
    else if (argc > 1) { usb = open_port(argv[1], O_RDWR | O_NOCTTY ); }

    struct termios oldterm, newterm;

    tcgetattr(fd, &oldtio); // Save old terminal settings

    bzero(&newtio, sizeof(newtio)); // Clear out struct
    if( setBaud(&newtio, 230400) != 0 ) { printf("Baud could not be set\n"); exit (EXIT_FAILURE); } // Set up baud rate

    newtio.c_cflag = CS8 | CREAD | CLOCAL; // 8 data bits, enable receiver, local line 
    newtio.c_cflag &= ~PARENB | ~CSTOPB; // No parity, one stop bit 
    newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable software flow control
    newtio.c_oflag = 0;
    newtio.c_lflag = 0;
    newtio.c_cc[VTIME] = 0; // No timeout clock for read
    newtio.c_cc[VMIN] = 1; // Wait for one character before reading another

    tcflush(fd, TCIFLUSH); 
    tcsetattr(fd, TCSANOW, &newtio); // Set fd with new settings immediately

    /* Do writing or reading from port in here - readIt or writeIt*/

    tcsetattr(fd, TCSANOW, &oldtio); // Set fd with old settings immediately
    close(fd); // Close fd

    return 0;
}

如果可能的话,我正在寻找最佳的写入和读取速率,此时没有数据损坏处理。通过优化,我说的是 termios 结构的配置标志的最佳设置。

谢谢您的帮助。

4

2 回答 2

0

关于第一点,很容易FILE*使用fdopen. 但是,您必须记住 aFILE*默认情况下是缓冲的,因此您写入的内容可能不会立即发送。

于 2014-01-09T08:05:22.757 回答
0

看看这个ANSI C 主机库,用于与 XBee 模块进行通信。该xbee_serial_posix.c文件包括一个完整的串行接口,驱动程序中的更高层提供 API 帧的解析和调度。还有很多示例程序。

您可以直接使用该库,也可以参考串行层来编写自己的 termios 串行代码。

它主要设计用于在“API 模式”( ATAP=1) 中使用 XBee 模块,但也有一些用于“AT 模式”的部分(如xbee_term示例)。

于 2014-01-10T18:23:09.340 回答