C++串口问题

发布于 2024-08-08 22:59:19 字数 1661 浏览 4 评论 0原文

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

Problem:
I have a hand held device that scans those graphic color barcodes on all packaging. There is a track device that I can use that will slide the device automatically. This track device functions by taking ascii code through a serial port. I need to get this thing to work in FileMaker on a Mac. So no terminal programs, etc...

What I've got so far:
I bought a Keyspan USB/Serial adapter. Using a program called ZTerm I was successful in sending commands to the device.
Example:
"C,7^M^J"

I was also able to do the same thing in Terminal using this command: screen /dev/tty.KeySerial1 57600
and then type in the same command above(but when I typed in I just hit Control-M and Control-J for the carriage return and line feed)

Now I'm writing a plug-in for FileMaker(in C++ of course). I want to get what I did above happen in C++ so when I install that plug-in in FileMaker I can just call one of those functions and have the whole process take place right there.

I'm able to connect to the device, but I can't talk to it. It is not responding to anything.

I've tried connecting to the device(successfully) using these:

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

and

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

This is what I've tried so far in way of talking to the device:

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

or

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

or

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

or

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

Questions:
When I connected to the device from Terminal and using ZTerm, I was able to set my baud rate of 57600. I think that may be why it isn't responding here. But I don't know how to do it here.... Does any one know how to do that? I tried this, but it didn't work:

comport->BaudRate = 57600;

There are a lot of class solutions out there but they all call these include files like termios.h and stdio.h. I don't have these and, for whatever reason, I can't find them to download. I've downloaded a few examples but there are like 20 files in them and they're all calling other files I can't find(like the ones listed above). Do I need to find these and if so where? I just don't know enough about C++ Is there a website where I can download libraries??

Another solution might be to put those terminal commands in C++. Is there a way to do that?

So this has been driving me crazy. I'm not a C++ guy, I only know basic programming concepts. Is anyone out there a C++ expert? I ideally I'd like this to just work using functions I already have, like those fwrite, fputs stuff.
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

凉世弥音 2024-08-15 22:59:19

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

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

编辑:可能比您(希望)需要知道的更多 - 但请阅读 串行端口指南,然后再继续。

Sending a ^ and then a M doesn't send control-M, thats just the way you write it,
to send a control character the easiest way is to just use the ascii control code.

ps. ^M is carriage return ie "\r" and ^J is linefeed "\n"

edit: Probably more than you will (hopefully) ever need to know - but read The Serial Port Howto before going any further.

╰ゝ天使的微笑 2024-08-15 22:59:19

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

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

This isn't a C++ question. You're asking how to interact with the TTY driver to set teh baud rate. The fact that you're opening the file under /dev tells me that you're on a unix derivative, so the relevant man page to read on a linux system is "man 3 termios".

Basically, you use the open() variant above, and pass the file descriptor to tcsetattr/tcgetattr.

橙味迷妹 2024-08-15 22:59:19

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

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

Are you sure you've installed all the compiler tools properly? On my OS X 10.5.8 Mac,
termios.h and stdio.h are right there under /usr/include, just as I'd expect. The
code you've already found for serial port programming on other Unix variants should
only require minor changes (if any) to work on a Mac. Can you tell us a bit more about
what you've tried, and what went wrong?

mgb also has a good point about how the control characters need to be represented.

━╋う一瞬間旳綻放 2024-08-15 22:59:19

您可以使用 ioctl 设置波特率。下面是示例链接

You can set the baud rate with ioctl. Here's a link to an example.

三生路 2024-08-15 22:59:19

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

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

步骤如下 -

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

计时参数意味着一旦

设置了终端参数,就可以从设备返回字符(使用 POSIX open()),然后可以使用 tcgetattr/tcsetattr 通过配置设备。 请

此时,您可以使用 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);
} 

You don't specify which Unix you are using, so below I'm posting some Linux production code I use.

Pleae note below code is a class method so ignore any external (ie undeclared) references.

Steps are as follows -

Configure your termio structure, this is where you set any needed flags etc (ie the step you accomplished using zterm. The termio settings below configure the port to 8 databits, 1 stopbit and no parity (8-n-1). Also the port will be in "raw" (as opposed to cooked) mode so its a character stream, text isn't framed into lines etc The baud constants match the actual value, ie for 56700 baud you use "57600".

The timing parameters mean that characters are returned from the device as soon as they are available.

Once you have your termainal parameters set, you open the device (using POSIX open()), and then can use tcgetattr/tcsetattr to configure the device via the fd.

At this point you can read/write to the device using the read()/write() system calls.

Note that in the below example read() will block if no data is available so you may want to use select()/poll() if blocking is undesirable.

Hope that helps.

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);
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文