单片机USB U盘实验 单片机 STM32F407开发板DMF407电机开发板平台keil V5.31HSE 为8MHZHSI为16MHZ一、申请内存exfuns_init(); /* 为fatfs相关变量申请内存 */uint8_t exfuns_init(void) { uint8_t i; uint8_t res 0; for (i 0; i FF_VOLUMES; i) { fs[i] (FATFS *)mymalloc(SRAMIN, sizeof(FATFS)); /* 为磁盘i工作区申请内存 */ if (!fs[i])break; } #if USE_FATTESTER 1 /* 如果使能了文件系统测试 */ res mf_init(); /* 初始化文件系统测试(申请内存) */ #endif if (i FF_VOLUMES res 0) { return 0; /* 申请有一个失败,即失败. */ } else { return 1; } }二、初始化USBH_Init(g_hUSBHost, USBH_UserProcess, HOST_FS);USBH_HandleTypeDef g_hUSBHost; /* USB Host处理结构体 */ /* USB Host handle structure */ typedef struct _USBH_HandleTypeDef { __IO HOST_StateTypeDef gState; /* Host State Machine Value */ ENUM_StateTypeDef EnumState; /* Enumeration state Machine */ CMD_StateTypeDef RequestState; USBH_CtrlTypeDef Control; USBH_DeviceTypeDef device; USBH_ClassTypeDef *pClass[USBH_MAX_NUM_SUPPORTED_CLASS]; USBH_ClassTypeDef *pActiveClass; uint32_t ClassNumber; uint32_t Pipes[16]; __IO uint32_t Timer; uint32_t Timeout; uint8_t id; void *pData; void (* pUser)(struct _USBH_HandleTypeDef *pHandle, uint8_t id); #if (USBH_USE_OS 1U) #if osCMSIS 0x20000 osMessageQId os_event; osThreadId thread; #else osMessageQueueId_t os_event; osThreadId_t thread; #endif uint32_t os_msg; #endif } USBH_HandleTypeDef; /* Following states are used for gState */ typedef enum { HOST_IDLE 0U, HOST_DEV_WAIT_FOR_ATTACHMENT, HOST_DEV_ATTACHED, HOST_DEV_DISCONNECTED, HOST_DETECT_DEVICE_SPEED, HOST_ENUMERATION, HOST_CLASS_REQUEST, HOST_INPUT, HOST_SET_CONFIGURATION, HOST_SET_WAKEUP_FEATURE, HOST_CHECK_CLASS, HOST_CLASS, HOST_SUSPENDED, HOST_ABORT_STATE, } HOST_StateTypeDef; /* Following states are used for EnumerationState */ typedef enum { ENUM_IDLE 0U, ENUM_GET_FULL_DEV_DESC, ENUM_SET_ADDR, ENUM_GET_CFG_DESC, ENUM_GET_FULL_CFG_DESC, ENUM_GET_MFC_STRING_DESC, ENUM_GET_PRODUCT_STRING_DESC, ENUM_GET_SERIALNUM_STRING_DESC, } ENUM_StateTypeDef; /* Following states are used for RequestState */ typedef enum { CMD_IDLE 0U, CMD_SEND, CMD_WAIT } CMD_StateTypeDef; /* Control request structure */ typedef struct { uint8_t pipe_in; uint8_t pipe_out; uint8_t pipe_size; uint8_t *buff; uint16_t length; uint16_t timer; USB_Setup_TypeDef setup; CTRL_StateTypeDef state; uint8_t errorcount; } USBH_CtrlTypeDef; /* Attached device structure */ typedef struct { uint8_t CfgDesc_Raw[USBH_MAX_SIZE_CONFIGURATION]; uint8_t Data[USBH_MAX_DATA_BUFFER]; uint8_t address; uint8_t speed; uint8_t EnumCnt; uint8_t RstCnt; __IO uint8_t is_connected; __IO uint8_t is_disconnected; __IO uint8_t is_ReEnumerated; uint8_t PortEnabled; uint8_t current_interface; USBH_DevDescTypeDef DevDesc; USBH_CfgDescTypeDef CfgDesc; } USBH_DeviceTypeDef; /* USB Host Class structure */ typedef struct { const char *Name; uint8_t ClassCode; USBH_StatusTypeDef(*Init)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*DeInit)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*Requests)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*BgndProcess)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*SOFProcess)(struct _USBH_HandleTypeDef *phost); void *pData; } USBH_ClassTypeDef; /* USB Host handle structure */ typedef struct _USBH_HandleTypeDef { __IO HOST_StateTypeDef gState; /* Host State Machine Value */ ENUM_StateTypeDef EnumState; /* Enumeration state Machine */ CMD_StateTypeDef RequestState; USBH_CtrlTypeDef Control; USBH_DeviceTypeDef device; USBH_ClassTypeDef *pClass[USBH_MAX_NUM_SUPPORTED_CLASS]; USBH_ClassTypeDef *pActiveClass; uint32_t ClassNumber; uint32_t Pipes[16]; __IO uint32_t Timer; uint32_t Timeout; uint8_t id; void *pData; void (* pUser)(struct _USBH_HandleTypeDef *pHandle, uint8_t id); #if (USBH_USE_OS 1U) #if osCMSIS 0x20000 osMessageQId os_event; osThreadId thread; #else osMessageQueueId_t os_event; osThreadId_t thread; #endif uint32_t os_msg; #endif } USBH_HandleTypeDef;static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id) { uint32_t total, free; uint8_t res 0; switch (id) { case HOST_USER_SELECT_CONFIGURATION: break; case HOST_USER_DISCONNECTION: f_mount(0, 1:, 1); /* 卸载U盘 */ lcd_show_string(30, 140, 200, 16, 16, U Disk connecting..., BLUE); lcd_fill(30, 160, 239, 220, WHITE); break; case HOST_USER_CLASS_ACTIVE: lcd_show_string(30, 140, 200, 16, 16, U Disk connect successful!, BLUE); f_mount(fs[1], 1:, 1); /* 重新挂载U盘 */ res exfuns_get_free(1:, total, free); if (res 0) { lcd_show_string(30, 160, 200, 16, 16, FATFS OK!, BLUE); lcd_show_string(30, 180, 200, 16, 16, U Disk Total Size: MB, BLUE); lcd_show_string(30, 200, 200, 16, 16, U Disk Free Size: MB, BLUE); lcd_show_num(174, 180, total 10, 5, 16, BLUE); /* 显示U盘总容量 MB */ lcd_show_num(174, 200, free 10, 5, 16, BLUE); } else { lcd_show_string(30, 160, 200, 16, 16, FATFS ERROR!, BLUE); printf(U盘存储空间获取失败\r\n); } break; case HOST_USER_CONNECTION: break; default: break; } }USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t id), uint8_t id) { /* Check whether the USB Host handle is valid */ if (phost NULL) { USBH_ErrLog(Invalid Host handle); return USBH_FAIL; } /* Set DRiver ID */ phost-id id; /* Unlink class*/ phost-pActiveClass NULL; phost-ClassNumber 0U; /* Restore default states and prepare EP0 */ DeInitStateMachine(phost); /* Restore default Device connection states */ phost-device.PortEnabled 0U; phost-device.is_connected 0U; phost-device.is_disconnected 0U; phost-device.is_ReEnumerated 0U; /* Assign User process */ if (pUsrFunc ! NULL) { phost-pUser pUsrFunc; } #if (USBH_USE_OS 1U) #if (osCMSIS 0x20000U) /* Create USB Host Queue */ osMessageQDef(USBH_Queue, MSGQUEUE_OBJECTS, uint16_t); phost-os_event osMessageCreate(osMessageQ(USBH_Queue), NULL); /* Create USB Host Task */ #if defined (USBH_PROCESS_STACK_SIZE) osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0U, USBH_PROCESS_STACK_SIZE); #else osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0U, 8U * configMINIMAL_STACK_SIZE); #endif /* defined (USBH_PROCESS_STACK_SIZE) */ phost-thread osThreadCreate(osThread(USBH_Thread), phost); #else /* Create USB Host Queue */ phost-os_event osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(uint32_t), NULL); /* Create USB Host Task */ USBH_Thread_Atrr.name USBH_Queue; #if defined (USBH_PROCESS_STACK_SIZE) USBH_Thread_Atrr.stack_size USBH_PROCESS_STACK_SIZE; #else USBH_Thread_Atrr.stack_size (8U * configMINIMAL_STACK_SIZE); #endif /* defined (USBH_PROCESS_STACK_SIZE) */ USBH_Thread_Atrr.priority USBH_PROCESS_PRIO; phost-thread osThreadNew(USBH_Process_OS, phost, USBH_Thread_Atrr); #endif /* (osCMSIS 0x20000U) */ #endif /* (USBH_USE_OS 1U) */ /* Initialize low level driver */ USBH_LL_Init(phost); return USBH_OK; }USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost) { /* Init USB_IP */ if (phost-id HOST_FS) { /* Link the driver to the stack. */ g_hhcd_USB_OTG_FS.Instance USB_OTG_FS; /* 使用USB_OTG */ g_hhcd_USB_OTG_FS.Init.Host_channels 8; /* 主机通道数为8个 */ g_hhcd_USB_OTG_FS.Init.speed HCD_SPEED_FULL; /* USB全速 12M */ g_hhcd_USB_OTG_FS.Init.dma_enable DISABLE; /* 不使用DMA */ g_hhcd_USB_OTG_FS.Init.phy_itface HCD_PHY_EMBEDDED; /* 使能内部PHY */ g_hhcd_USB_OTG_FS.Init.Sof_enable DISABLE; /* 禁止SOF中断 */ g_hhcd_USB_OTG_FS.Init.vbus_sensing_enable 0; /* 不使能VBUS检测 */ g_hhcd_USB_OTG_FS.Init.lpm_enable 0; /* 不使能连接电源管理 */ g_hhcd_USB_OTG_FS.Init.low_power_enable 0; /* 不使能低功耗模式 */ g_hhcd_USB_OTG_FS.pData phost; /* g_hhcd_USB_OTG_FS的pData指向phost */ phost-pData g_hhcd_USB_OTG_FS; /* phost的pData指向g_hhcd_USB_OTG_FS */ if (HAL_HCD_Init(g_hhcd_USB_OTG_FS) ! HAL_OK) /* 初始化LL驱动 */ { printf(USB Init ERROR \r\n); } else { printf(USB Init OK \r\n); } USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(g_hhcd_USB_OTG_FS)); } return USBH_OK; }HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd) { USB_OTG_GlobalTypeDef *USBx; /* Check the HCD handle allocation */ if (hhcd NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_HCD_ALL_INSTANCE(hhcd-Instance)); USBx hhcd-Instance; if (hhcd-State HAL_HCD_STATE_RESET) { /* Allocate lock resource and initialize it */ hhcd-Lock HAL_UNLOCKED; #if (USE_HAL_HCD_REGISTER_CALLBACKS 1U) hhcd-SOFCallback HAL_HCD_SOF_Callback; hhcd-ConnectCallback HAL_HCD_Connect_Callback; hhcd-DisconnectCallback HAL_HCD_Disconnect_Callback; hhcd-PortEnabledCallback HAL_HCD_PortEnabled_Callback; hhcd-PortDisabledCallback HAL_HCD_PortDisabled_Callback; hhcd-HC_NotifyURBChangeCallback HAL_HCD_HC_NotifyURBChange_Callback; if (hhcd-MspInitCallback NULL) { hhcd-MspInitCallback HAL_HCD_MspInit; } /* Init the low level hardware */ hhcd-MspInitCallback(hhcd); #else /* Init the low level hardware : GPIO, CLOCK, NVIC... */ HAL_HCD_MspInit(hhcd); #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */ } hhcd-State HAL_HCD_STATE_BUSY; /* Disable DMA mode for FS instance */ if ((USBx-CID (0x1U 8)) 0U) { hhcd-Init.dma_enable 0U; } /* Disable the Interrupts */ __HAL_HCD_DISABLE(hhcd); /* Init the Core (common init.) */ (void)USB_CoreInit(hhcd-Instance, hhcd-Init); /* Force Host Mode*/ (void)USB_SetCurrentMode(hhcd-Instance, USB_HOST_MODE); /* Init Host */ (void)USB_HostInit(hhcd-Instance, hhcd-Init); hhcd-State HAL_HCD_STATE_READY; return HAL_OK; }​ void HAL_HCD_MspInit(HCD_HandleTypeDef *hcdHandle) { GPIO_InitTypeDef gpio_init_struct { 0 }; if (hcdHandle-Instance USB_OTG_FS) { __HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能GPIOA时钟 */ gpio_init_struct.Pin GPIO_PIN_11 | GPIO_PIN_12; gpio_init_struct.Mode GPIO_MODE_AF_PP; /* 复用 */ gpio_init_struct.Pull GPIO_NOPULL; /* 浮空 */ gpio_init_struct.Speed GPIO_SPEED_FREQ_VERY_HIGH; /* 高速 */ gpio_init_struct.Alternate GPIO_AF10_OTG_FS; /* 复用为OTG_FS */ HAL_GPIO_Init(GPIOA, gpio_init_struct); /* 初始化PA11和PA12引脚 */ USBH_Delay(100); __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); /* 使能OTG FS时钟 */ HAL_NVIC_SetPriority(OTG_FS_IRQn, 1, 2); /* 优先级设置为抢占1,子优先级2 */ HAL_NVIC_EnableIRQ(OTG_FS_IRQn); /* 使能OTG FS中断 */ } } ​三、注册USBH_RegisterClass(g_hUSBHost, USBH_MSC_CLASS);#define USBH_MSC_CLASS USBH_msc USBH_ClassTypeDef USBH_msc { MSC, USB_MSC_CLASS, USBH_MSC_InterfaceInit, USBH_MSC_InterfaceDeInit, USBH_MSC_ClassRequest, USBH_MSC_Process, USBH_MSC_SOFProcess, NULL, };USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass) { USBH_StatusTypeDef status USBH_OK; if (pclass ! NULL) { if (phost-ClassNumber USBH_MAX_NUM_SUPPORTED_CLASS) { /* link the class to the USB Host handle */ phost-pClass[phost-ClassNumber] pclass; status USBH_OK; } else { USBH_ErrLog(Max Class Number reached); status USBH_FAIL; } } else { USBH_ErrLog(Invalid Class handle); status USBH_FAIL; } return status; }四、启动USBH_Start(g_hUSBHost);USBH_StatusTypeDef USBH_Start(USBH_HandleTypeDef *phost) { /* Start the low level driver */ USBH_LL_Start(phost); /* Activate VBUS on the port */ USBH_LL_DriverVBUS(phost, TRUE); return USBH_OK; }USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost) { HAL_StatusTypeDef hal_status HAL_OK; USBH_StatusTypeDef usb_status USBH_OK; hal_status HAL_HCD_Start(phost-pData); usb_status USBH_Get_USB_Status(hal_status); return usb_status; }USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, uint8_t state) { if (phost-id HOST_FS) { if (state 0) { /* 没有用到VBUS检测 */ } else { /* 没有用到VBUS检测 */ } } USBH_Delay(200); return USBH_OK; }五、处理while (1) { USBH_Process(g_hUSBHost); delay_ms(10); t; if (t 50) { t 0; LED0_TOGGLE(); } }static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id) { uint32_t total, free; uint8_t res 0; switch (id) { case HOST_USER_SELECT_CONFIGURATION: break; case HOST_USER_DISCONNECTION: f_mount(0, 1:, 1); /* 卸载U盘 */ lcd_show_string(30, 140, 200, 16, 16, U Disk connecting..., BLUE); lcd_fill(30, 160, 239, 220, WHITE); break; case HOST_USER_CLASS_ACTIVE: lcd_show_string(30, 140, 200, 16, 16, U Disk connect successful!, BLUE); f_mount(fs[1], 1:, 1); /* 重新挂载U盘 */ res exfuns_get_free(1:, total, free); if (res 0) { lcd_show_string(30, 160, 200, 16, 16, FATFS OK!, BLUE); lcd_show_string(30, 180, 200, 16, 16, U Disk Total Size: MB, BLUE); lcd_show_string(30, 200, 200, 16, 16, U Disk Free Size: MB, BLUE); lcd_show_num(174, 180, total 10, 5, 16, BLUE); /* 显示U盘总容量 MB */ lcd_show_num(174, 200, free 10, 5, 16, BLUE); } else { lcd_show_string(30, 160, 200, 16, 16, FATFS ERROR!, BLUE); printf(U盘存储空间获取失败\r\n); } break; case HOST_USER_CONNECTION: break; default: break; } }测试结果、U盘与串口有干涉、U盘与串口有干涉、U盘