C ++串口问题

时间:2009-10-20 18:14:36

标签: c++ unix serial-port filemaker

问题: 我有一个手持设备,扫描所有包装上的图形颜色条形码。我可以使用跟踪设备自动滑动设备。该跟踪设备通过串行端口获取ascii代码。我需要让这个东西在Mac上的FileMaker中运行。所以没有终端程序等......

到目前为止我的内容: 我买了一个Keyspan USB /串口适配器。使用名为ZTerm的程序,我成功地向设备发送命令。 例: “C,7 ^ M ^ J”

我还可以使用此命令在终端中执行相同的操作:screen /dev/tty.KeySerial1 57600 然后输入上面的相同命令(但是当我输入时,我只需按Control-M和Control-J进行回车和换行)

现在我正在为FileMaker编写一个插件(当然是用C ++编写的)。我希望得到我在C ++中所做的事情,所以当我在FileMaker中安装该插件时,我可以调用其中一个函数并让整个过程在那里进行。

我可以连接到设备,但我无法与之通信。它没有回应任何事情。

我尝试使用以下方法(成功)连接到设备:

FILE *comport;
if ((comport = fopen("/dev/tty.KeySerial1", "w")) == NULL){...}

int fd;
fd = open("/dev/tty.KeySerial1", O_RDWR | O_NOCTTY | O_NDELAY);

这是我到目前为止与设备交谈时所尝试的内容:

fputs ("C,7^M^J",comport);

fprintf(comport,"C,7^M^J");

char buffer[] = { 'C' , ',' , '7' , '^' , 'M' , '^' , 'J' };
fwrite (buffer , 1 , sizeof(buffer) , comport );

fwrite('C,7^M^J', 1, 1, comport);

问题: 当我从终端连接到设备并使用ZTerm时,我能够将波特率设置为57600.我认为这可能就是为什么它在这里没有响应。但我不知道该怎么做......有谁知道怎么做?我试过这个,但它不起作用:

comport->BaudRate = 57600;

有许多类解决方案,但它们都称为包括termios.h和stdio.h等文件。我没有这些,无论出于何种原因,我找不到它们下载。我已经下载了一些例子,但是其中有20个文件,他们都在调用我找不到的其他文件(如上面列出的那些文件)。我是否需要找到这些,如果是这样的话?我对C ++还不够了解是否有可以下载库的网站?

另一种解决方案可能是将这些终端命令放在C ++中。有没有办法做到这一点?

所以这让我发疯了。我不是C ++人,我只懂基本的编程概念。有人在那里是C ++专家吗?理想情况下,我希望能够使用我已经拥有的函数,比如fwrite,fputs。 谢谢!

5 个答案:

答案 0 :(得分:5)

发送^然后M不发送control-M,就像你编写它一样, 发送控制字符最简单的方法就是使用ascii control代码。

PS。 ^ M是回车符,即“\ r”,^ J是换行符“\ n”

编辑:可能比您(希望)需要知道的更多 - 但在继续之前阅读The Serial Port Howto

答案 1 :(得分:1)

这不是C ++问题。你问的是如何与TTY驱动程序交互以设置波特率。您在/ dev下打开文件的事实告诉我您使用的是unix派生词,因此在linux系统上阅读的相关手册页是“man 3 termios”。

基本上,您使用上面的open()变体,并将文件描述符传递给tcsetattr / tcgetattr。

答案 2 :(得分:0)

您确定已正确安装所有编译器工具吗?在我的OS X 10.5.8 Mac上, 正如我所期望的那样,termios.h和stdio.h就在/ usr / include下。该 您已经找到的用于其他Unix变体的串口编程的代码应该 只需要在Mac上进行微小的更改(如果有的话)。你能告诉我们更多的信息吗? 你尝试了什么,出了什么问题?

mgb对于如何表示控制字符也有一个很好的观点。

答案 3 :(得分:0)

您可以使用ioctl设置波特率。这是一个link to an example

答案 4 :(得分:0)

你没有指定你正在使用的Unix,所以下面我发布了一些我使用的Linux生产代码。

请注意下面的代码是一个类方法,因此忽略任何外部(即未声明的)引用。

步骤如下 -

配置你的termio结构,这是你设置任何所需标志等的地方(即你使用zterm完成的步骤。下面的termio设置将端口配置为8个数据位,1个停止位和无奇偶校验(8-n-1)。此外,端口将处于“原始”(与煮熟相反)模式,因此它的字符流,文本不会被划分为行等等。波特常量与实际值匹配,即对于56700波特,您使用“57600”。

时序参数表示字符一旦可用就会从设备返回。

设置好termainal参数后,打开设备(使用POSIX open()),然后可以使用tcgetattr / tcsetattr通过fd配置设备。

此时,您可以使用read()/ write()系统调用来读取/写入设备。

请注意,在下面的示例中,如果没有可用的数据,则read()将阻塞,因此如果不希望阻塞,您可能需要使用select()/ poll()。

希望有所帮助。

termios termio    
tcflag_t baud_specifier;

    //reset device state...
    memset (&termio, 0, sizeof (termios));
    read_buffer.clear();

    //get our boad rate...
    if (!(baud_specifier = baud_constant (baud))) {
        ostringstream txt;
        txt << "invalid baud - " << baud;
        device_status_msg = txt.str();
        status = false;

        return (true);
    }


    //configure device state...
    termio.c_cflag = baud_specifier | CS8 | CLOCAL | CREAD;

    //do we want handshaking?
    if (rtscts) {
        termio.c_cflag |= CRTSCTS;
    }

    termio.c_iflag = IGNPAR;
    termio.c_oflag = 0;
    termio.c_lflag = 0;

    //com port timing, no wait between characters and read unblocks as soon as there is a character
    termio.c_cc[VTIME]    = 0;
    termio.c_cc[VMIN]     = 0;

    //open device...
    if ((fd = open (device.c_str(), O_RDWR | O_NOCTTY)) == -1) {

        ostringstream txt;
        txt << "open(\"" << device << "\") failed with " << errno << " - "
            << std_error_msg (errno);
        device_status_msg = txt.str();
        status = false;

        return (true);
    }

    //keep a copy of curret device state...
    if (tcgetattr (fd, &old_termio) == -1) {

        ostringstream txt;
        txt << "tcgetattr() failed with " << errno << " - " << std_error_msg (errno);
        device_status_msg = txt.str();
        status = false;

        return (true);
    }

    //flush any unwanted bytes
    if (tcflush (fd, TCIOFLUSH) == -1) {

        ostringstream txt;
        txt << "tcflush() failed with " << errno << " - " << std_error_msg (errno);
        device_status_msg = txt.str();
        status = false;

        return (true);
    }

    //apply our device config...
    if (tcsetattr (fd, TCSANOW, &termio) == -1) {

        ostringstream txt;
        txt << "tcsetattr() failed with " << errno << " - " << std_error_msg (errno);
        device_status_msg = txt.str();
        status = false;

        return (true);
    }

    node_log_f ("successfully initialised device %s at %i baud", "open_device()",
                device.c_str(), baud);

    status = true;
    return (true);
}