2

问题:我有一个手持设备,可以扫描所有包装上的图形彩色条码。我可以使用一个轨道设备,它会自动滑动设备。该跟踪设备通过串行端口获取 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 的东西。谢谢!

4

5 回答 5

5

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

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

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

于 2009-10-20T18:31:35.987 回答
1

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

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

于 2009-10-20T18:41:50.483 回答
0

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

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

于 2009-10-20T18:39:07.687 回答
0

您可以使用ioctl设置波特率。这是一个示例的链接

于 2009-10-20T18:47:57.350 回答
0

您没有指定您使用的是哪个 Unix,所以下面我将发布一些我使用的 Linux 生产代码。

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

步骤如下——

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

时序参数意味着字符一可用就从设备返回。

设置好终端参数后,打开设备(使用 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);
} 
于 2009-10-21T07:07:00.807 回答