历史上的今天
返回首页

历史上的今天

今天是:2024年09月17日(星期二)

2018年09月17日 | STM32 USB 上位机程序实现

2018-09-17 来源: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

#include

#include

#include


#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;

}


编译


编译代码可以使用 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 编写的上位机程序。


推荐阅读

史海拾趣

Anaheim Automation公司的发展小趣事

近年来,随着全球金属氧化物压敏电阻市场的不断增长,AMOTECH也迎来了新的发展机遇。根据市场研究报告,预计全球金属氧化物压敏电阻市场规模将以稳定的增速持续增长。AMOTECH凭借其在该领域的深厚积累和不断创新的技术实力,有望在未来市场中占据更加重要的地位。同时,公司也将继续加大研发投入,拓展新的应用领域,为电子行业的发展贡献更多力量。

这些故事框架主要基于已知的事实和信息构建而成,旨在展示AMOTECH公司在电子行业中的发展历程和重要成就。然而,由于具体细节可能涉及公司内部信息或商业机密,因此无法提供更为详细和具体的描述。如需了解更多关于AMOTECH公司的故事和发展历程,建议查阅相关新闻报道或公司官方资料。

Analog Modules Inc公司的发展小趣事

随着公司技术的不断进步和产品质量的提升,AMOTECH在1996年被政府通讯部评为“光明前途企业”。这是对公司技术实力和市场潜力的认可,也为公司的后续发展提供了有力支持。同年,公司还获得了ISO9000认证,这标志着公司的质量管理体系达到了国际标准,为公司进一步拓展国际市场打下了坚实基础。

Antex公司的发展小趣事

随着业务的不断扩展,Antex在1980年决定将工厂从东京都大田区羽田迁至茨城县高萩市。这一搬迁不仅为公司提供了更广阔的发展空间,也标志着Antex开始向着全球化布局迈进。此后,公司积极寻求国际合作,与全球各地的供应商和客户建立了紧密的合作关系。

Crane Connectors公司的发展小趣事

Crane Connectors公司深知产品质量是企业生存和发展的根本。因此,公司始终将质量管理放在首位,建立了完善的质量管理体系。从原材料采购、生产加工到产品检验、售后服务,每一个环节都严格把控,确保产品质量符合国际标准和客户要求。同时,公司还不断引进先进的质量管理理念和技术手段,提升质量管理水平。这些举措使得公司的产品质量得到了客户的高度认可,进一步提升了公司的市场竞争力。

Bridgelux公司的发展小趣事

XXXX年,中国电子信息产业集团公司(CEC)和重庆临空开发投资公司牵头收购了Bridgelux。这次收购为Bridgelux带来了强大的资本支持和市场资源,使其得以进一步扩大生产规模,提升研发能力。在CEC和重庆临空的支持下,Bridgelux在全球范围内的市场份额逐步提升,品牌影响力不断增强。

High Energy Corp公司的发展小趣事

XXXX年,中国电子信息产业集团公司(CEC)和重庆临空开发投资公司牵头收购了Bridgelux。这次收购为Bridgelux带来了强大的资本支持和市场资源,使其得以进一步扩大生产规模,提升研发能力。在CEC和重庆临空的支持下,Bridgelux在全球范围内的市场份额逐步提升,品牌影响力不断增强。

问答坊 | AI 解惑

电子密码锁

要在原图中加入二极管指示电路,每按一个键二极管闪烁一下,请问如何画图? 开锁电路 用继电器如何设计一个??? 拜托帮帮忙啊!很着急!…

查看全部问答>

使用synplify综合遇到的两点疑问

请教如下两个问题:       1. synplify不能综合状态机的“when others”状态:我用的是VHDL,编码风格中要求对case语句的使用要做到取值完全覆盖,即要加一个“when others”的判断(我想Verilog也一样吧,用default?),用c ...…

查看全部问答>

依靠DeviceIoControl获得 的硬盘信息能区别pda设备吗?

依靠DeviceIoControl获得 的硬盘信息对于每一个pda设备 是唯一的吗? …

查看全部问答>

RegOpenKeyEx在动态库和exe中的问题

各位前辈:     相同的代码在动态库中调用RegOpenKeyEx RegCreateKeyEx返回不是ERROR_SUCCESS,是-11881138260,而用EVC调试就返回0即ERROR_SUCCESS,有谁遇到过?搞了几天了没进展,哪位前辈遇到过指点一二,谢谢啊!…

查看全部问答>

进入不了PendSV_Handler

我使用STM32F103VC的芯片跑UCOS。但是执行了如下的代码就是进入不了PendSV_Handler。用软件仿真还是可以的,但是烧到板上就不可以了。执行这段代码的时候BASEPRI = 0,PRIMASK = 0.这应该没有关中断吧。为什么就是进入不了 ...…

查看全部问答>

问个DMA的问题

我用c6711做一个图像采集的卡,数据从FIFO中输入到DSP外接SDRAM中,二者都映射到DSP存储空间,我请问一下,可不可以使用DMA方式实现FIFO与SDRAM间的直接数据传输?(不进DSP),应该怎样做?可能我说得不是很明白,我是想使用DSP控制FIFO与SDRAM间 ...…

查看全部问答>

心情

天天加班,这领导当的真累!!…

查看全部问答>

BKP求助

怎样将掉电的数据保存下来,我现在要实现一个功能:用STM32做的一个系统突然掉电后,再来电系统自动开机启动。 我想要用BKP来实现,目前BKP的寄存器已经用了5个,DR1,DR2,DR3,DR4,DR5用作掉电RTC用,我用DR6记录正常关机的数据,然后上电时对其进行 ...…

查看全部问答>

献给新手 改变从这里开始

这是我在网上看到的一篇帖子,作者是古木(胡斌)老师写的,作为一名在读学生,我也感到迷茫,我也为自己曾经的无所事事而感到无可奈何,也想在一念之间将所有的东西都学会,然后找到高薪工作,但往往是欲速则不达,古木老师的这篇文章是他经验的总 ...…

查看全部问答>

STM32以太网数据接收中断函数是那个?

我正在使用stm32_eth_lib固件库,我希望能将以太网接收到的数据通过USB转发到上位机(我只需要将以太网物理层接收到的一帧数据经过USB转发到上位机,不需要经过协议栈)。但是 找不到以太网接收到数据后的中断处理函数,以太网是数据是通过DMA通道传 ...…

查看全部问答>