提问者:小点点

编写一个基于libusb的与Ardino通信的程序


我编写了以下程序来与Arduino Uno进行通信。 这个测试程序让用户每次从PC发送一个字节到Arduino板。 如果宽接收字节序列65,71,67,68,UNO宽将闪烁内置LED,并将相同的序列65,71,67,68写入串行缓冲器。 我所写的Arduino草图按预期工作(我用串行监视器检查了它)。

但C++程序并不总是接收到完整的字节序列。
在不同的迭代中,接收到的序列可以是(65,71,67,68)或(65,71,67)或(65,71)或65或0。 如果能有一些见解,将不胜感激。

#include "libusb.h"
#include <iostream>`
#include <stdio.h>`
#include <string.h>`
#include <unistd.h>`

libusb_device_handle *dev_handle;
libusb_context *ctx = NULL;

static int ENDPOINT_IN  = 0x83;
static int ENDPOINT_OUT = 0x04;

static const int    USB_TIMEOUT = 2000;     

int CLOSE_DEVICE();
int OPEN_DEVICE();

int main(){

if(OPEN_DEVICE()!=0){
    printf("Device Open Failed!\n");
    libusb_close(dev_handle); 
    libusb_exit(ctx); 
    return -1;
}


int rc=-1;
    
unsigned char encoding[] = { 0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08 }; //9600 1N8

    rc = libusb_control_transfer(dev_handle,0x21, 0x20, 0, 0, encoding,7, 0);
    if (rc < 0) {
        
            printf("ERROR IN CONTROL TRANSFER!\n");
    }

unsigned char cUsbBuf[64]={0,0,0,0};
unsigned char iUsbBuf[64]={0,0,0,0};
int   nBytes=0;
int status =-1;
unsigned char character=0;

        
    while(1){

        printf("send byte:");
        scanf("%u",&character); 

        if(character==255){
            break;
        }else{
            cUsbBuf[0] = static_cast<unsigned char>(character);
        }

        status = libusb_bulk_transfer(dev_handle, (ENDPOINT_OUT|LIBUSB_ENDPOINT_OUT),cUsbBuf,1,&nBytes, USB_TIMEOUT);
        if(status<0){
            printf("TRANSFER ERROR:%s\n",libusb_error_name(status));
        }

        printf(")ut Bytes:%d\n",nBytes);
        usleep(2000000);
        
        status = libusb_bulk_transfer(dev_handle,(ENDPOINT_IN|LIBUSB_ENDPOINT_IN),iUsbBuf,4,&nBytes, USB_TIMEOUT);
    
        if(status<0){
            printf("TRANSFER ERROR:%s\n",libusb_error_name(status));
        }
        printf("in Bytes:%d\n",nBytes);
    
        for(int i=0;i<4;++i){
            printf("%d ", iUsbBuf[i]);
            iUsbBuf[i]=0;
        }
        printf("\n\n\n");
        nBytes=0;

                    
    }
    


CLOSE_DEVICE();

return 0;

}

int CLOSE_DEVICE(){

if(libusb_release_interface(dev_handle, 0)!=0){ //release the claimed interface 0
    printf("Error releasing interface 0 !\n",1);
        return -1;
    }


if(libusb_release_interface(dev_handle, 1)!=0){ //release the claimed interface 1
    printf("Error releasing interface 1 !\n",1);
        return -1;
    }

libusb_close(dev_handle); 

libusb_exit(ctx); 

return 0;

}

int OPEN_DEVICE(){

libusb_device **devs;
ssize_t cnt; 

if(libusb_init(&ctx)<0){
    printf("ERROR INIT!");
    return -1;
} 
    
cnt=libusb_get_device_list(ctx, &devs);
    
dev_handle = libusb_open_device_with_vid_pid(ctx,0x2341,0x0043); //ARIDUNO UNO VENDER and DEVICE ID 0x2341:0x0043

if(dev_handle == NULL){
    printf("ERROR OPENING!");
        return -1;
}
    else{
        printf("UNO OPENED!\n");
}

libusb_free_device_list(devs, 1);
libusb_reset_device(dev_handle);

if(libusb_set_configuration(dev_handle,1)<0){
    printf("SET CONFIG ERROR!\n");
}   

for(int k=0;k<2;++k){

    if(libusb_kernel_driver_active(dev_handle, k) == 1) { 

            printf("KERNEL DRIVER ACTIVE:INTERFACE %d\n",k);
        if(libusb_detach_kernel_driver(dev_handle, k) != 0){ 
            printf("ERROR KERNEL DETACH:INTERFACE %d\n",k);
                return -1;
        }
        }
            
    if(libusb_claim_interface(dev_handle, k)<0){
        printf("ERROR CLAM INTERFACE %d!\n",k);
        return -1;
    }

    printf("INTERFACE %d CLAMED!\n",k);

}

return 0;

}

这里还附上了Arduino草图。

unsigned char buff[] = {0, 0, 0, 0};

    void setup() {
        Serial.begin(9600);
        while (!Serial){
           ;
        }
        Serial.setTimeout(5000);
        pinMode(LED_BUILTIN, OUTPUT);
    }
    
void loop() {}

void serialEvent() {

  if (Serial.available() >= 4) {

      Serial.readBytes(buff, 4);

      if ((buff[0] == 65) && (buff[1] == 71) && (buff[2] == 67) && (buff[3] == 68)) {
      
      Serial.write(buff,4);
      Serial.flush();
      digitalWrite(LED_BUILTIN, HIGH);
      buff[0]=buff[1]=buff[2]=buff[3]=0x0;
      delay(500);

      }
    
    digitalWrite(LED_BUILTIN, LOW);

  }
}

这里附加了编译器输出

g++ -Wall -fPIC -Wextra -Werror -pedantic -pedantic-errors -O3 -I. -o UNOTEST UNOTest_2.cpp -L/home/mkovash/sis3153/libUSB1Driver/libusb-1.0.23/exports/lib -Bstatic -lusb-1.0
In file included from UNOTest_2.cpp:1:0:
libusb.h:741:46: error: ISO C++ forbids zero-size array ‘dev_capability_data’ [-Wpedantic]
  uint8_t dev_capability_data[ZERO_SIZED_ARRAY];
                                              ^
libusb.h:766:78: error: ISO C++ forbids zero-size array ‘dev_capability’ [-Wpedantic]
  struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY];
                                                                              ^
libusb.h:1259:70: error: ISO C++ forbids zero-size array ‘iso_packet_desc’ [-Wpedantic]
  struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY];
                                                                      ^
UNOTest_2.cpp: In function ‘int main()’:
UNOTest_2.cpp:48:9: error: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Werror=unused-result]
    scanf("%u",&character);
    ~~~~~^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors

共1个答案

匿名用户

scanf转换说明符%d需要一个int*,但您在此处为它提供了一个无符号字符*:

scanf("%d", &character);

这使得您的程序具有未定义的行为。 scanf可能会在无符号字符之后向内存中额外写入3个字节。

如果您想继续使用scanf,则使character成为无符号int:

unsigned character;
scanf("%u", &character);
// ...
if(character>255) break;
cUsbBuf[0] = static_cast<unsigned char>(character);