STM32 USB 上位机程序实现

libusb 介绍

libusb是开源的C库,使用该库是的用户可以在应用程序中直接访问 USB 设备,无需为 USB 设备编写内核驱动。libusb支持多个平台 (Linux, window, iOS),所以可以很方便地将应用程序移植到其他平台。

linux libusb 安装

从网上下载libusb的源码,下载地址:http://www.libusb.org/, 下载后编译安装。

# tar jxvf libusb-1.0.20.tar.bz2

# cd libusb-1.0.20
# ./configure
# make
# sudo make install
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

ubuntu下可以通过以下命令快速安装。

sudo apt-get isntall libusb*
 
 
  • 1
  • 1

安装后,libusb的头文件被安装在/usr/local/include/libusb-1.0 ,链接库被安装在/usr/loacal/lib目录下。

usb bulk 传输例程

这个例程演示如何使用 libusb 库,编写 USB bulk xfer 上位机demo,可以正常接收和发送数据。注意,修改程序中的 VID 和 PID 的值和你 device 板子上所定义的一致,传输数据块的大小不要超过 device 定义的最大传输长度。


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "libusb.h"

#define VID 0x8888
#define PID 0x0088

#define edp2in 0x82
#define edp2out 0x02

int main(void)
{
    libusb_device **devs, *dev;
    int ret, i;
    ssize_t cnt;
    usb_pro_t usb_pro;
    struct libusb_device_handle *handle = NULL;
    libusb_context *ctx = NULL;

    ret = libusb_init(&ctx);
    if (ret < 0)
        return -1;

    libusb_set_debug(ctx, 3);

    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0) {
        printf("no usb dev on bus\r\n");
        return  -1;
    }

    i = 0;
    while((dev = devs[i++]) != NULL) {

        ret = libusb_get_device_descriptor(dev,&desc);
        if (ret < 0) {
            printf("failed to get device descriptor");
            goto error;
        }

        if ((desc.idVendor == VID) && (desc.idProduct == PID)) {
            printf("bLength: 0x%04x\r\n", desc.bLength);
            printf("bDescriptorType: 0x%04x\r\n", desc.bDescriptorType);
            printf("bcdUSB: 0x%04x\r\n", desc.bcdUSB);
            printf("bDeviceClass: 0x%04x\r\n", desc.bDeviceClass);
            printf("bDeviceSubClass: 0x%04x\r\n", desc.bDeviceSubClass);
            printf("bDeviceProtocol: 0x%04x\r\n", desc.bDeviceProtocol);
            printf("bMaxPacketSize0: 0x%04x\r\n", desc.bMaxPacketSize0);
            printf("vendor id: 0x%04x\r\n", desc.idVendor);
            printf("product id: 0x%04x\r\n", desc.idProduct);
            printf("bcdDevice: 0x%04x\r\n", desc.bcdDevice);
            printf("iManufacturer: 0x%04x\r\n", desc.iManufacturer);
            printf("iProduct: 0x%04x\r\n", desc.iProduct);
            printf("iSerialNumber: 0x%04x\r\n", desc.iSerialNumber);
            printf("bNumConfigurations: 0x%04x\r\n", desc.bNumConfigurations);

        }

    }

    handle = libusb_open_device_with_vid_pid(ctx, VID, PID);

    if (handle == NULL) {
        printf("cant't open device\r\n");
        goto error;
    } else {
        printf("open device\r\n");
    }

    libusb_free_device_list(devs, 1);

    if (libusb_kernel_driver_active(handle, 0) ==1) {
        printf("kernel driver active, detach it \r\n");

        if (libusb_detach_kernel_driver(handle, 0) == 0) {
            printf("detached kernel driver\r\n");
        }
        else {
            goto error;
        }
    }

    ret = libusb_claim_interface(handle, 0);
    if (ret < 0) {
        printf("can't claim interface\r\n");
        goto error;
    } else {
        printf("claimed interface\r\n");
    }

    char data[64];
    int actual_len = 0;
    int didi = 1000;
    for (int i = 0; i< 1000; i++) {
        memset(data, 0, sizeof(data));
        /*  receive data from device  */
        /*
        ret = libusb_bulk_transfer(handle, edp2in, data, 64, &actual_len, 0);

        if (actual_len = 0) {
            printf("received nothing\r\n");
        } else {
            printf("bulk transfer: %s\r\n", data);
        }

        usleep(200000);
        */

        char *str = "am host";

        sprintf(data, "am host %d\r\n", i);

        ret = libusb_bulk_transfer(handle, edp2out, data, strlen(data), &actual_len, 0);

        if (actual_len != 0) {
            printf("send data: %s\r\n", data);
        }

        usleep(200000); 
    }

    libusb_close(handle);

error:

    printf("free device list\r\n");
    libusb_free_device_list(devs, 1);

    libusb_exit(NULL);

    return 0;
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137

编译

编译代码可以使用 makefile 文件,也可以是使用命令行命令编译,这里给出两种编译方法。

  • makefile

CC = gcc

# your libusb library path, be careful your path.
LDIR = /usr/loacal/lib

# link flag
LFLAG = -lusb-1.0

# libusb hearder file path
INCLUDES = /usr/local/include/libusb-1.0

CFLAGS = -I$(INCLUDES) -std=c99

src = $(wildcard *.c)

obj = $(patsubst %.c, %.o, $(src))

.PHONY: all clean

all: main

main: $(obj)
    $(CC)   $(obj) -o main -L$(LDIR) $(LFLAG)

%.o:%.c
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    @-rm -f main $(obj)

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 命令行编译 
    命令中-I/usr/local/include/libusb-1.0 告诉编译器 libusb 的头文件所在的路径。-L/usr/local/lib/ 告诉链接器所要链接的库文件路径。-lusb-1.0 告诉编译器需要链接 libusb-1.0.so这个库。
 gcc -I/usr/local/include/libusb-1.0 -std=c99 main.c -o main -L/usr/local/lib/ -lusb-1.0

 
 
  • 1
  • 2
  • 1
  • 2

运行

编译后会在当前目录下生成一个名叫“main“的可执行文件,运行这个文件。如果打开USB设备时出错提示permission error,那么使用

# sudo ./main
 
 
  • 1
  • 1

运行后,HOST每隔200ms 向 device 发送一个数据包。

源码下载

我的源码已上传到http://download.csdn.net/detail/chengwenyang/9479835 ,包含STM32F4Discovery板子的 usb bulk 传输的工程文件和 使用 libusb 编写的上位机程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值