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