ST(意法半导体公司)为STM32系列处理器编写了外设USB的库,并提供了很好的参考例程,本文就是参考ST提供的例程,在STM32F4 discovery板子上实现usb bulk传输。Host端是在linux平台上利用libusb库函数写的读写USB应用。
本次实现在STM32 USB例程中的Device HID 鼠标例程基础上添加bulk传输端点修改而来。
usb_conf.h 文件中添加 bulk传输端点
#define HID_IN_EP 0x81
#define HID_OUT_EP 0x01
#define HID_IN_PACKET 4
#define HID_OUT_PACKET 4
#define HID_IN_BULK_EP 0x82 // endpoint in
#define HID_OUT_BULK_EP 0x02 // endpoint out
#define HID_IN_BULK_PACKET 64
#define HID_OUT_BULK_PACKET 64
usb_desc.c 中修改设备描述符
把bDeviceClass值改为0xFF,表示用户自定义设备;修改VID 和 PID,例如以下程序中的值。
__ALIGN_BEGIN uint8_t USBD_DeviceDesc[USB_SIZ_DEVICE_DESC] __ALIGN_END =
{
0x12,
USB_DEVICE_DESCRIPTOR_TYPE,
0x00,
0x02,
0xff,
0x00,
0x00,
USB_OTG_MAX_EP0_SIZE,
LOBYTE(USBD_VID),
HIBYTE(USBD_VID),
LOBYTE(USBD_PID),
HIBYTE(USBD_PID),
0x00,
0x02,
USBD_IDX_MFC_STR,
USBD_IDX_PRODUCT_STR,
USBD_IDX_SERIAL_STR,
USBD_CFG_MAX_NUM
} ;
- 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
修改配置描述符
在原有的鼠标配置描述符中添加bulk xfer的两个端点描述符(IN and OUT)。最后, 记得修改配置描述符的长度,不然配置描述符传输不完整。
在usbd_hid_core.h 文件中修改配置描述符的大小 USB_HID_CONFIG_DESC_SIZ
#define USB_HID_CONFIG_DESC_SIZ 46
配置描述符中的接口描述符也要做相应的调整,将端点数目 bNumEndpoints 改为4个,将接口子类bInterfaceSubClass改成 0x00, 将接口协议改成0x00。nInterfaceProtocol 修改成0x00。具体描述见下面代码中的注释。
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09,
USB_CONFIGURATION_DESCRIPTOR_TYPE,
USB_HID_CONFIG_DESC_SIZ,
0x00,
0x01,
0x01,
0x00,
0xE0,
0x32,
/************** Descriptor of Joystick Mouse interface ****************/
0x09,
USB_INTERFACE_DESCRIPTOR_TYPE,
0x00,
0x00,
0x04,
0x00,
0x00,
0x00,
0,
/******************** Descriptor of Mouse endpoint ********************/
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
HID_IN_EP,
0x03,
HID_IN_PACKET,
0x00,
0x0A,
/******************** Descriptor of Mouse endpoint ********************/
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
HID_OUT_EP,
0x03,
HID_IN_PACKET,
0x00,
0x0A,
/******************** Descriptor of bulk xfer endpoint ********************/
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
HID_IN_BULK_EP,
0x02,
HID_IN_BULK_PACKET,
0x00,
0x0A,
/******************** Descriptor of bulk xfer endpoint ********************/
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
HID_OUT_BULK_EP,
0x02,
HID_OUT_BULK_PACKET,
0x00,
0x0A,
} ;
- 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
至此,描述符的修改就完成了。由于是bulk传输,所以不需要定义报告描述符,只有中断传输和控制传输需要定义报告描述符。接下来需要添加发送和接收数据的接口函数了。
初始化端点
usb_hid_core.c 中,HID 初始化函数中添加对 bulk I/O 端点的初始化,直接追加在鼠标所使用端点后面。在最后又添加了bulk xfer OUT 端口的发送初始化函数,以便让USB知道当接收到数据后数据该存储到哪儿。数组 USB_Rx_Buffer[HID_OUT_BULK_PACKET] 是用户自己定义的一个数据缓冲区,大小设为该端点的最大包长度即可。
static uint8_t USBD_HID_Init (void *pdev,
uint8_t cfgidx)
{
printf("%s\r\n", __FUNCTION__);
DCD_EP_Open(pdev,
HID_IN_EP,
HID_IN_PACKET,
USB_OTG_EP_INT);
DCD_EP_Open(pdev,
HID_OUT_EP,
HID_OUT_PACKET,
USB_OTG_EP_INT);
DCD_EP_Open(pdev,
HID_IN_BULK_EP,
HID_IN_BULK_PACKET,
USB_OTG_EP_BULK);
DCD_EP_Open(pdev,
HID_OUT_BULK_EP,
HID_OUT_BULK_PACKET,
USB_OTG_EP_BULK);
DCD_EP_PrepareRx(pdev,
HID_OUT_BULK_EP,
(uint8_t*)(USB_Rx_Buffer),
HID_OUT_BULK_PACKET);
return USBD_OK;
}
- 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
添加 OUT 端点接收HOST发出数据的回调函数。类似地,添加 IN端点回调函数发送数据到HOST
在usb_hid_core.c 中,修改USB_HID_cb 函数数组中的函数指针。
USBD_Class_cb_TypeDef USBD_HID_cb =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL,
NULL,
USBD_HID_DataIn,
USBD_HID_DataOut,
NULL,
NULL,
NULL,
USBD_HID_GetCfgDesc,
#ifdef USB_OTG_HS_CORE
USBD_HID_GetCfgDesc,
#endif
};
static uint8_t USBD_HID_DataOut (void *pdev, uint8_t epnum)
{
uint16_t USB_Rx_Cnt;
USB_Rx_Cnt = ((USB_OTG_CORE_HANDLE*)pdev)->dev.out_ep[epnum].xfer_count;
DCD_EP_PrepareRx(pdev,
HID_OUT_BULK_EP,
(uint8_t*)(USB_Rx_Buffer),
HID_OUT_BULK_PACKET);
return USBD_OK;
}
static uint8_t USBD_HID_DataIn(void *pdev, uint8_t epnum)
{
int USB_Tx_length = HID_IN_BULK_PACKET;
DCD_EP_Tx (pdev,
CDC_IN_EP,
(uint8_t*)&APP_Rx_Buffer[USB_Tx_ptr],
USB_Tx_length);
return USBD_OK;
}
- 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
验证
将USB代码编译后下载到STM32F4Discovery 板子上运行,连接USB线到PC,windows操作系统下在设备管理器中可以看到HID设备,查看VID/PID 或者USB 显示出的Product string和你代码中设定的一致的就是我们的USB 设备。
STM32 USB 上位机软件实现
请查看 STM32 USB 上位机程序实现,利用 libusb 在 linux 平台上 使用 bulk xfer 和 STM32F4Discovery 传输数据。对应的源码在 http://download.csdn.net/detail/chengwenyang/9479835 可以下载。
from:http://blog.csdn.net/chengwenyang/article/details/51039741