2017-01-12 11 views
1

Мне нужно прочитать отклик от блока управления двигателем. После записи команды, начинающейся с ?, блок двигателя должен ответить некоторым текстом. То есть на ?MSG он должен сообщить о своем статусе. Но когда я пытаюсь прочитать статус, блок ничего не отправляет, и запрос заканчивается таймаутом.Почему чтение с lsusb не удается?

Код довольно прост и использует libusb. Программа отсоединяет все активные драйверы от устройства, присоединяется к устройству, передает команду ?MSG и ждет ответа. После этого он отсоединяется и кончается.

Почему нет ответа? Есть ли ошибка в коде или проблема с двигателем? Я уверен, что команды отправляются и принимаются блоком в качестве двигателя движется, например, на PSET1=4000

#include <assert.h> 
#include <string.h> 

#define VENDOR_ID  0x0483 
#define PRODUCT_ID 0x5740 
#define BULK_EP_IN  0x03 
#define BULK_EP_OUT  0x81 // From computer to control unit 
#define INTERFACE_IN  0 
#define INTERFACE_OUT  1 

#define BUF_SIZE 64 

int main() 
{ 
    libusb_context *ctx; 
    libusb_device_handle *dev_handle; 
    int r = 0; 
    int actual, length, received; 
    char cmd[] = "?MSG\r\n"; 
    char buffer[BUF_SIZE]; 
    length = strlen(cmd); 
    r = libusb_init(&ctx); 
    assert(r == 0); 

    /* Set verbosity level to 3, as suggested in the documentation */ 
    libusb_set_debug(ctx, 3); 

    /* Get device handle */ 
    dev_handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID); 
    assert(dev_handle != NULL); 

    /* Find out if kernel driver is attached on IN iface */ 
    if(libusb_kernel_driver_active(dev_handle, INTERFACE_IN) == 1) { 
     printf("Kernel Driver Active\n"); 
     assert(libusb_detach_kernel_driver(dev_handle, INTERFACE_IN) == 0); 
     printf("Kernel Driver Detached!\n"); 
    } 
    if(libusb_kernel_driver_active(dev_handle, INTERFACE_OUT) == 1) { 
     printf("Kernel Driver Active\n"); 
     assert(libusb_detach_kernel_driver(dev_handle, INTERFACE_OUT) == 0); 
     printf("Kernel Driver Detached!\n"); 
    } 

    /* Claim IN interface of device */ 
    r = libusb_claim_interface(dev_handle, INTERFACE_IN); 
    assert(r >= 0); 
    /* claim OUT interface of device */ 
    r = libusb_claim_interface(dev_handle, INTERFACE_OUT); 
    assert(r >= 0); 


    /* Transfer commands */ 
    r = libusb_bulk_transfer(dev_handle, BULK_EP_IN, (unsigned char *)cmd, length, &actual, 0); 
    assert(r == 0 && actual > 0 && actual == length); 
    printf("Written %s\n",cmd); 

    /* Now read response */ 
    if (cmd[0] == '?') { 
     char buffer[BUF_SIZE] = ""; 
     int received = 0; 
     do { 
      int i; 
      r = libusb_bulk_transfer(dev_handle, BULK_EP_OUT, (unsigned char *)buffer, BUF_SIZE, &received, 1000); 
      if(r == LIBUSB_ERROR_TIMEOUT) { 
       printf("Timeout\n"); 
      } else { 
       assert(r == 0); 
      } 
      for(i = 0; i<BUF_SIZE;i++) 
       printf("%c",buffer[i]); 
     } while (received != 0); 
    } 

    /* Release devices */ 
    r = libusb_release_interface(dev_handle, INTERFACE_IN); 
    assert(r == 0); 
    r = libusb_release_interface(dev_handle, INTERFACE_OUT); 
    assert(r == 0); 

    /* Clean */ 
    libusb_close(dev_handle); 
    libusb_exit(ctx); 
} 

Ниже приводится описание устройства с sudo lsusb --verbose в случае, если это важно:

Bus 003 Device 003: ID 0483:5740 STMicroelectronics STM32F407 
Device Descriptor: 
    bLength    18 
    bDescriptorType   1 
    bcdUSB    2.00 
    bDeviceClass   2 Communications 
    bDeviceSubClass   0 
    bDeviceProtocol   0 
    bMaxPacketSize0  64 
    idVendor   0x0483 STMicroelectronics 
    idProduct   0x5740 STM32F407 
    bcdDevice   1.00 
    iManufacturer   1 STMicroelectronics 
    iProduct    2 STR75x Virtual COM Port 
    iSerial     3 Demo 1.000 
    bNumConfigurations  1 
    Configuration Descriptor: 
    bLength     9 
    bDescriptorType   2 
    wTotalLength   67 
    bNumInterfaces   2 
    bConfigurationValue  1 
    iConfiguration   0 
    bmAttributes   0xc0 
     Self Powered 
    MaxPower    0mA 
    Interface Descriptor: 
     bLength     9 
     bDescriptorType   4 
     bInterfaceNumber  0 
     bAlternateSetting  0 
     bNumEndpoints   1 
     bInterfaceClass   2 Communications 
     bInterfaceSubClass  2 Abstract (modem) 
     bInterfaceProtocol  1 AT-commands (v.25ter) 
     iInterface    0 
     CDC Header: 
     bcdCDC    1.10 
     CDC Call Management: 
     bmCapabilities  0x00 
     bDataInterface   1 
     CDC ACM: 
     bmCapabilities  0x02 
      line coding and serial state 
     CDC Union: 
     bMasterInterface  0 
     bSlaveInterface   1 
     Endpoint Descriptor: 
     bLength     7 
     bDescriptorType   5 
     bEndpointAddress  0x82 EP 2 IN 
     bmAttributes   3 
      Transfer Type   Interrupt 
      Synch Type    None 
      Usage Type    Data 
     wMaxPacketSize  0x0008 1x 8 bytes 
     bInterval    255 
    Interface Descriptor: 
     bLength     9 
     bDescriptorType   4 
     bInterfaceNumber  1 
     bAlternateSetting  0 
     bNumEndpoints   2 
     bInterfaceClass  10 CDC Data 
     bInterfaceSubClass  0 Unused 
     bInterfaceProtocol  0 
     iInterface    0 
     Endpoint Descriptor: 
     bLength     7 
     bDescriptorType   5 
     bEndpointAddress  0x03 EP 3 OUT 
     bmAttributes   2 
      Transfer Type   Bulk 
      Synch Type    None 
      Usage Type    Data 
     wMaxPacketSize  0x0040 1x 64 bytes 
     bInterval    0 
     Endpoint Descriptor: 
     bLength     7 
     bDescriptorType   5 
     bEndpointAddress  0x81 EP 1 IN 
     bmAttributes   2 
      Transfer Type   Bulk 
      Synch Type    None 
      Usage Type    Data 
     wMaxPacketSize  0x0040 1x 64 bytes 
     bInterval    0 
Device Status:  0x0001 
    Self Powered 
+0

С очень беглого чтения вы действительно поменяли свои ссылки на «OUT» и «IN». Они всегда с точки зрения хоста (ПК, т. Е. Вашего), поэтому вы должны писать в 'OUT' и читать из' IN'. – unwind

+0

Это определенно не заменено. Если я изменяю конечные точки, программа зависает при первом вызове 'libusb_bulk_transfer()'. Таким образом, я по крайней мере могу отправить команды. – Kostrahb

ответ

0

Вы можете связываться с устройством по протоколу RS-232, поскольку он предоставляет виртуальный COM-порт , который является классом CDC ACM. Драйвер ядра - cdc_acm.

iManufacturer   1 STMicroelectronics 
    iProduct    2 STR75x Virtual COM Port 
    bInterfaceClass   2 Communications 
    bInterfaceSubClass  2 Abstract (modem) 
    bInterfaceProtocol  1 AT-commands (v.25ter) 
    iInterface    0 
    CDC Header: 
    bcdCDC    1.10 
    CDC Call Management: 
    bmCapabilities  0x00 
    bDataInterface   1 
    CDC ACM: 
    bmCapabilities  0x02 
     line coding and serial state 
    CDC Union: 
    bMasterInterface  0 
    bSlaveInterface   1 

Таким образом, вы можете установить связь с устройством, посылая команду RS-232 в /dev/ttyACMx (или /dev/ttyUSBx) (вместо й с номером на вашей системе)

Чтобы проверить это, вы можете использовать терминальную программу, как PuTTY, ... 5 Linux/Unix Commands For Connecting To The Serial Console. Вы должны выяснить параметры правильно COM порта (скорость передачи, четность, старт/стоп-биты и т.д.)

Есть несколько библиотек, RS-232, см C: cross-platform RS-232 serial library?

Проверьте dmesg выход после того, как плагин в устройстве, чтобы увидеть, какой драйвер используется.