单片机USB U盘实验

单片机 :STM32F407

开发板:DMF407电机开发板

平台:keil V5.31

HSE 为8MHZ

HSI为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;
    }
}

测试结果:

1、U盘1#,与串口有干涉

2、U盘2#,与串口有干涉

3、U盘3#

相关推荐
FreakStudio5 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘10 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u1521096484910 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd84510150010 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼10 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
wohoo_wangzi10 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
✎ ﹏梦醒͜ღ҉繁华落℘11 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展11 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司11 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设
踏着七彩祥云的小丑11 天前
嵌入式测试学习第 37 天:异常场景测试:断电、拔插、干扰、非法指令
单片机·嵌入式硬件·学习