简体   繁体   English

C ++串口问题

[英]C++ Serial Port Question

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. 该跟踪设备通过通过串行端口获取ASCII码来发挥作用。 I need to get this thing to work in FileMaker on a Mac. 我需要让此东西在Mac上的FileMaker中工作。 So no terminal programs, etc... 因此没有终端程序等。

What I've got so far : I bought a Keyspan USB/Serial adapter. 到目前为止,我所拥有的 :我购买了Keyspan USB /串行适配器。 Using a program called ZTerm I was successful in sending commands to the device. 使用名为ZTerm的程序,我成功向设备发送了命令。 Example: "C,7^M^J" 示例:“ 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) 我还可以使用以下命令在终端中执行相同的操作:screen /dev/tty.KeySerial1 57600,然后在上方输入相同的命令(但是当我输入时,我只需要按Control-M和Control-J即可返回和换行)

Now I'm writing a plug-in for FileMaker(in C++ of course). 现在,我正在为FileMaker(当然是C ++)编写一个插件。 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. 我想获得我在C ++中所做的一切,所以当我在FileMaker中安装该插件时,我可以仅调用其中一个函数,并在此进行整个过程。

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. 问题 :当我从终端连接到设备并使用ZTerm时,我可以将波特率设置为57600。我认为这可能就是为什么它在这里没有响应的原因。 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. 那里有很多类解决方案,但是他们都称它们包括termios.h和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). 我已经下载了一些示例,但是其中有20个文件,它们都在调用我找不到的其他文件(例如上面列出的文件)。 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?? 我对C ++不够了解,是否有一个网站可以下载库?

Another solution might be to put those terminal commands in C++. 另一个解决方案可能是将这些终端命令放入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. 我不是C ++的人,我只知道基本的编程概念。 Is anyone out there a C++ expert? 有没有人是C ++专家? I ideally I'd like this to just work using functions I already have, like those fwrite, fputs stuff. 理想情况下,我希望它可以使用已经拥有的功能(例如fwrite,fputs之类的东西)工作。 Thanks! 谢谢!

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. 先发送一个^,然后再发送一个M,不会发送control-M,这只是您编写它的方式,发送控制字符的最简单方法是仅使用ascii控制代码。

ps. PS。 ^M is carriage return ie "\\r" and ^J is linefeed "\\n" ^ M是回车符,即“ \\ r”,而^ J是换行符“ \\ n”

edit: Probably more than you will (hopefully) ever need to know - but read The Serial Port Howto before going any further. 编辑:可能比您(希望)要知道的更多-但是在继续之前请阅读《串行端口方法》

This isn't a C++ question. 这不是C ++问题。 You're asking how to interact with the TTY driver to set teh baud rate. 您在询问如何与TTY驱动程序进行交互以设置波特率。 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". 您打开/ dev下的文件的事实表明您使用的是unix派生,因此在linux系统上要阅读的相关手册页是“ man 3 termios”。

Basically, you use the open() variant above, and pass the file descriptor to tcsetattr/tcgetattr. 基本上,您使用上面的open()变体,并将文件描述符传递给tcsetattr / tcgetattr。

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. 正如我期望的那样,在我的OS X 10.5.8 Mac上,termios.h和stdio.h就在/ usr / include下。 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. 您已经找到的用于在其他Unix变体上进行串行端口编程的代码,只需稍作更改(如果有的话)即可在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. mgb还很好地说明了如何表示控制字符。

You can set the baud rate with ioctl . 您可以使用ioctl设置波特率。 Here's a link to an example . 这是一个示例链接

You don't specify which Unix you are using, so below I'm posting some Linux production code I use. 您没有指定要使用的Unix,所以下面我发布了一些Linux生产代码。

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". 配置termio结构,在这里可以设置任何需要的标志等(即使用zterm完成的步骤。下面的termio设置将端口配置为8个数据位,1个停止位和无奇偶校验(8-n-1)。也是该端口将处于“原始”(相对于煮熟的)模式,因此其字符流,文本未成帧等。波特常数与实际值匹配,即对于56700波特,请使用“ 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. 设置了终端参数后,打开设备(使用POSIX open()),然后可以使用tcgetattr / tcsetattr通过fd配置设备。

At this point you can read/write to the device using the read()/write() system calls. 此时,您可以使用read()/ write()系统调用来读取/写入设备。

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. 请注意,在以下示例中,如果没有可用数据,则read()将阻塞,因此,如果不希望阻塞,则可能要使用select()/ poll()。

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);
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM