发送命令并等待回复USB设备

Sending command and waiting for reply to a USB device

本文关键字:回复 USB 设备 等待 命令      更新时间:2023-10-16

我有一个设备(旋转测量表)连接到/dev/ttyACM0,并且需要编写一个简单的CPP控制器以将命令发送到设备并收听响应。

我没有这种东西的经验。我了解我可以使用fstream打开USB设备,并使用write()发送命令。有效。

问题是我如何发送命令并开始收听响应?

下面的代码只是悬挂。我猜是因为它是同步的,因此错过了响应。

#include <iostream>
#include <fstream>
#include <string>
int main()
{
    std::fstream f;
    char command[256] = "?ASTATnr";
    char response[256];
    std::string str;
    f.open("/dev/ttyACM0");
    if (f.is_open())
    {
        std::cout << "Port opened" << std::endl;
    }
    f.write(command, 256);
    while(1)
    { 
       while (f >> str)
       {
          std::cout << str;
       }
    }
    return 0;
}

我已经研究了异步的libusb-1.0,但遇到问题,发现我的出路http://libusb.sourceforge.net/api-1.0/group__libus_elibusb_asyncio.html并从。

编辑:我设法使设备响应如下:

std::string response_value = "";
char response = 0;
std::cout << "response: ";
while(1)
{
    f << command;
    f.read(&response, 1);
    if ((int)response == 13)
    {
        break;
    }
    std::cout << (response) << " ";
    response_value += response;
}

与制作人交谈并尝试不同的命令并输出消息后,我发现该设备应发送可变长度响应,该响应始终以0x0D或Integer结束。

当前,如果我彼此之间发送多个命令,则什么也不会发生。从其他来源,我了解我需要设置波特率,但是,fstream没有文件描述符,并且`tcgetAttr(2)1 reauires文件描述符以初始化术语OILIOS结构。有没有办法检索它?

我最好回答问题。可以将作为文件读/写入USB设备,因为OS具有处理通信的驱动程序(如果我理解错误的话,请纠正我)。FSTREAM能够阅读和写作,但是由于调整MUS在终端级别上进行,因此不可能调整BAUD速率(设备为通信的频率),因此取决于OS。对于Linux,我们必须使用fctl.htermios.hunistd.h。它允许我们设置速率,以及超时,以防设备没有响应。

因此,仅使用CPP函数实施阅读和写作要复杂得多。

我在这里发布我的解决方案,这对我有用,但是欢迎对此发表任何评论。

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <string>
#include <iostream>
bool init_terminal_interface(struct termios& tty, const int file_descriptor)
{
    memset(&tty, 0, sizeof tty); // Init the structure;
    if (tcgetattr(file_descriptor, &tty) != 0)
    {
        std::cout << "Error" << errno << " from tcgetattr: " << strerror(errno) << std::endl;
        return false;
    }
    /* Set Baud Rate */
    cfsetospeed (&tty, (speed_t)B9600);
    cfsetispeed (&tty, (speed_t)B9600);

    /* Setting other Port Stuff */
    tty.c_cflag     &=  ~PARENB;            // Make 8n1
    tty.c_cflag     &=  ~CSTOPB;
    tty.c_cflag     &=  ~CSIZE;
    tty.c_cflag     &=  ~ICANON;
    tty.c_cflag     |=  CS8;
    tty.c_cflag     &=  ~CRTSCTS;           // no flow control
    tty.c_cc[VMIN]   =  0;                  // 
    tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
    tty.c_cflag     |=  CREAD | CLOCAL;     // turn on READ & ignore ctrl lines
    /* Flush Port, then applies attributes */
    tcflush(file_descriptor, TCIFLUSH);
    if (tcsetattr(file_descriptor, TCSANOW, &tty) != 0) {
        std::cout << "Error " << " from tcsetattr: " << strerror(errno) << std::endl;
        return false;
    }
    return true;
}
void send_command(std::string command, const int file_descriptor)
{
    write(file_descriptor, command.c_str(), command.size());
    std::cout << "Command sent: " << command << std::endl;
}
std::string check_response(int file_descriptor)
{
    std::string response_value = "";
    char response = 0;
    ssize_t n_read = 0;
    do {
        // In blocking mode, read() will return 0 after timeout.
        n_read = read( file_descriptor, &response, 1 );
        if (n_read > 0)
        {
            response_value += response;
        }
    } while( response != 'r' && (int)response != 13 && n_read != 0);
    // In case of timeout it will return an empty string.
    return response_value;
}
int open_serial(const std::string serial_path)
{
    int file_descriptor = open(serial_path.c_str(), O_RDWR);
    if (file_descriptor == -1)
    {
        std::cout << "Unable to access the turntable device." << std::endl;
        return -1;
    }
    std::cout << "File opened: " << file_descriptor << std::endl;
    struct termios tty;
    init_terminal_interface(tty, file_descriptor);
    return file_descriptor;
}
int main()
{
    int file_descriptor = open_serial("/dev/ttyACM0");
    if (file_descriptor == -1)
    {
        return 1;
    }
    // Good command.
    std::string command = "?baudratern";
    send_command(command, file_descriptor);
    std::string response_value = check_response(file_descriptor);
    std::cout << "Full response: " << response_value << std::endl;
    // Wrong command.
    command = "?asasdtatrn";
    send_command(command, file_descriptor);
    response_value = check_response(file_descriptor);
    std::cout << "Full response: " << response_value << std::endl;
    // Good command.
    command = "init1rn";
    send_command(command, file_descriptor);
    response_value = check_response(file_descriptor);
    std::cout << "Full response: " << response_value << std::endl;
    // Good command.
    command = "ref1=4rn";
    send_command(command, file_descriptor);
    response_value = check_response(file_descriptor);
    std::cout << "Full response: " << response_value << std::endl;
    return 0;
}