STM32F3HAL USB设备免驱动
USB现在变得越来越重要了,最近在修改的过程中发现了很多坑,而且这个方面的很多资料在网络上都没有讲得很清楚,这里使用hal库操作一下。
1.STM32F1和F3系列带USB的IO口内部没有上拉或下拉电阻(F4的自带)。想要达到全速或者检测得到,就得在外部加 1.5K上拉电阻,使用一个IO口来控制。CubeMX在生成USB代码后,还需要手动添加控制代码,这部分在标准库的USB demo中,使用了一个默认接口,也可以手动修改更换。
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_RESET);
/*Configure GPIO pin : PE3 */
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
}
然后在usbd_conf.c里找到void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)函数,在里面添加
void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
{
/* USER CODE BEGIN 6 */
if (state == 1)
{
/* Configure Low connection state. */
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_RESET);//使能下拉
}
else
{
/* Configure High connection state. */
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_SET);//使能上拉
}
/* USER CODE END 6 */
}
然后USB就能正常检测到了
下面的就是我自己的笔记了,做的是HID设备免驱动。
首先使用cubeMX生成一个HID设备,可以不用更改里面的参数。
增加断点
在对应的数组里面添加,例如
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END
第一个就是节点数,第二个不能修改,第3个和第4个可以自己定义。
增加完毕后需要在下面描述这个端点,这里定义为中断模式,大小16。
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (OUT)*/
USB_ENDPOINT_TYPE_INTERRUPT, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 16 Byte max */
0x00,
0x02, /*bInterval: Polling Interval (2 ms)*/
以下是模式类别,控制,同步,批量,中断。在HID模式下只能中断。如果选批量,需要驱动,而这个驱动,可以通过一些软件做出来,但是没有数字签名,如果自己用还可以,商用还是找微软集成一个吧,就是费钱。。。
#define USB_ENDPOINT_TYPE_CONTROL 0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
#define USB_ENDPOINT_TYPE_BULK 0x02
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
同样,HID设备还需要端点报告
这是是一个鼠标的
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END
里面增加
//输出报告
0x09, 0x05,//用法(vendor defined)
0x09, 0x06,//用法(vendor defined)
0x15, 0x80,//逻辑最小值(0x80 or -128)
0x25, 0x7F,//逻辑最大值(0x7F or 127)
0x35, 0x00,//物理最小值(0)
0x45, 0xFF,//物理最大值(255)
0x75, 0x08,//报告长度(8位)
0x95, 0x40,//报告数值(64 fields)
0x91, 0x02,//输出(data, variable, absolute)
接下来就是初始化和相关控制函数里添加这个端点了,这里的端点是HID_EPOUT_ADDR
(1) 在static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)函数里添加,第二个参数是端点,依次是传输类型,大小
USBD_LL_OpenEP(pdev,HID_EPOUT_ADDR,USBD_EP_TYPE_INTR,HID_EPIN_SIZE);
(2) 在static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx)函数里添加;就是加一个关闭端点地址
USBD_LL_CloseEP(pdev,HID_EPOUT_ADDR);
(3) 在usbd_conf.c里,函数USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)里添加,最后一个参数根据实际情况添加
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR, PCD_SNG_BUF, 0x140);
HAL库里面都是集成好的
例如判断USB状态
while(((USBD_HID_HandleTypeDef *)(&hUsbDeviceFS)->pClassData)->state == HID_BUSY){;}
然后调用USBD_LL_Transmit函数就可以发送数据了