单片机
返回首页

STM32在Ubuntu上编写USB上位机程序实现

2018-10-13 来源:eefocus

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

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


sudo apt-get isntall libusb*

安装后,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: 0xx\r\n', desc.bLength);

            printf('bDescriptorType: 0xx\r\n', desc.bDescriptorType);

            printf('bcdUSB: 0xx\r\n', desc.bcdUSB);

            printf('bDeviceClass: 0xx\r\n', desc.bDeviceClass);

            printf('bDeviceSubClass: 0xx\r\n', desc.bDeviceSubClass);

            printf('bDeviceProtocol: 0xx\r\n', desc.bDeviceProtocol);

            printf('bMaxPacketSize0: 0xx\r\n', desc.bMaxPacketSize0);

            printf('vendor id: 0xx\r\n', desc.idVendor);

            printf('product id: 0xx\r\n', desc.idProduct);

            printf('bcdDevice: 0xx\r\n', desc.bcdDevice);

            printf('iManufacturer: 0xx\r\n', desc.iManufacturer);

            printf('iProduct: 0xx\r\n', desc.iProduct);

            printf('iSerialNumber: 0xx\r\n', desc.iSerialNumber);

            printf('bNumConfigurations: 0xx\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;

}

编译


编译代码可以使用 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)

命令行编译 

命令中-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

运行


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


# sudo ./main

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


源码下载


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


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • PIC单片机控制的遥控防盗报警器电路

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 如何构建一个触摸传感器电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章