STM32F407入口函数USBD_Init详解
2022-06-14
1157
2
从前面可知,USBD_Init是USB设备的初始化函数,这里USB后面的D是指DEVICE的意思。
USBD_Init全代码为:
void USBD_Init(USB_OTG_CORE_HANDLE *pdev,
USB_OTG_CORE_ID_TypeDef coreID,
USBD_DEVICE *pDevice,
USBD_Class_cb_TypeDef *class_cb,
USBD_Usr_cb_TypeDef *usr_cb)
{
/* Hardware Init */
USB_OTG_BSP_Init(pdev);
USBD_DeInit(pdev);
/*Register class and user callbacks */
pdev->dev.class_cb = class_cb;
pdev->dev.usr_cb = usr_cb;
pdev->dev.usr_device = pDevice;
/* set USB OTG core params */
DCD_Init(pdev , coreID);
/* Upon Init call usr callback */
pdev->dev.usr_cb->Init();
/* Enable Interrupts */
USB_OTG_BSP_EnableInterrupt(pdev);
}
第一步为初始化STM32F407对应的管脚PA11和PA12,详见:http://www.usbzh.com/article/detail-1064.html
不过前面的文章有少说了一步就是对PA15置1.
//USB主机电源控制接口
#define USB_HOST_PWRCTRL PAout(15) //PA15
USB_HOST_PWRCTRL=1;
其原理图如下:
可以看到,这里用到了场效率管MOSFET,其型号为SI2301,这是一个P沟通的MOSFET.
所以,S一直为高电平,当G为低电平时MOSFET导通给D极电泊输出,不过G为低电平的前提是三级管导通,故USB_PWR为高电时,也即PA15输出为高电平。
模电快忘光了,还给王应吉老师了,不知道分析的对不对。
第二步为USBD_DeInit,是个空函数,应该给用户软件层初始化用。
/*Register class and user callbacks */
pdev->dev.class_cb = class_cb;
pdev->dev.usr_cb = usr_cb;
pdev->dev.usr_device = pDevice;
后面就是三个结构体的指针赋值,就是回调函数。前面有说过。详见:http://www.usbzh.com/article/detail-1065.html
再就是DCD_Init调用,这是对设备状态、端点参数的默认初始化,根据配置对寄存器、工作模式写入等与硬件相关的。
void DCD_Init(USB_OTG_CORE_HANDLE *pdev ,
USB_OTG_CORE_ID_TypeDef coreID)
{
uint32_t i;
USB_OTG_EP *ep;
//根据配置的工作模式实始化USB参数,如端点数量,FIFO大小等。
USB_OTG_SelectCore (pdev , coreID);
pdev->dev.device_status = USB_OTG_DEFAULT;
pdev->dev.device_address = 0;
/* Init ep structure */
for (i = 0; i < pdev->cfg.dev_endpoints ; i++)
{
ep = &pdev->dev.in_ep[i];
/* Init ep structure */
ep->is_in = 1;
ep->num = i;
ep->tx_fifo_num = i;
/* Control until ep is actvated */
ep->type = EP_TYPE_CTRL;
ep->maxpacket = USB_OTG_MAX_EP0_SIZE;
ep->xfer_buff = 0;
ep->xfer_len = 0;
}
for (i = 0; i < pdev->cfg.dev_endpoints; i++)
{
ep = &pdev->dev.out_ep[i];
/* Init ep structure */
ep->is_in = 0;
ep->num = i;
ep->tx_fifo_num = i;
/* Control until ep is activated */
ep->type = EP_TYPE_CTRL;
ep->maxpacket = USB_OTG_MAX_EP0_SIZE;
ep->xfer_buff = 0;
ep->xfer_len = 0;
}
/* disable USB Global interrupt */
USB_OTG_DisableGlobalInt(pdev);
/*Init the Core (common init.) */
USB_OTG_CoreInit(pdev);
/* Force Device Mode*/
USB_OTG_SetCurrentMode(pdev, DEVICE_MODE);
/* Init Device */
USB_OTG_CoreInitDev(pdev);
/* Enable USB Global interrupt */
USB_OTG_EnableGlobalInt(pdev);
}
调用初始化回调函数。
/* Upon Init call usr callback */
pdev->dev.usr_cb->Init();
最后就是USB中断NVIC的配置。
/* Enable Interrupts */
USB_OTG_BSP_EnableInterrupt(pdev);
void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//ÇÀÕ¼ÓÅÏȼ¶0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;//×ÓÓÅÏȼ¶3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//ʹÄÜͨµÀ
NVIC_Init(&NVIC_InitStructure);//ÅäÖÃ
}
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936