单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
一、初始化USB
USBD_Init(&USBD_Device, &VCP_Desc, DEVICE_FS); /* 初始化USB */
typedef struct _USBD_HandleTypeDef
{
uint8_t id;
uint32_t dev_config;
uint32_t dev_default_config;
uint32_t dev_config_status;
USBD_SpeedTypeDef dev_speed;
USBD_EndpointTypeDef ep_in[16];
USBD_EndpointTypeDef ep_out[16];
__IO uint32_t ep0_state;
uint32_t ep0_data_len;
__IO uint8_t dev_state;
__IO uint8_t dev_old_state;
uint8_t dev_address;
uint8_t dev_connection_status;
uint8_t dev_test_mode;
uint32_t dev_remote_wakeup;
uint8_t ConfIdx;
USBD_SetupReqTypedef request;
USBD_DescriptorsTypeDef *pDesc;
USBD_ClassTypeDef *pClass;
void *pClassData;
void *pUserData;
void *pData;
void *pBosDesc;
void *pConfDesc;
} USBD_HandleTypeDef;
USBD_HandleTypeDef USBD_Device; /* USB Device处理结构体 */
/* Private variables --------------------------------------------------------- */
USBD_DescriptorsTypeDef VCP_Desc = {
USBD_VCP_DeviceDescriptor,
USBD_VCP_LangIDStrDescriptor,
USBD_VCP_ManufacturerStrDescriptor,
USBD_VCP_ProductStrDescriptor,
USBD_VCP_SerialStrDescriptor,
USBD_VCP_ConfigStrDescriptor,
USBD_VCP_InterfaceStrDescriptor,
};
/* USB Device descriptors structure */
typedef struct
{
uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#if (USBD_CLASS_USER_STRING_DESC == 1)
uint8_t *(*GetUserStrDescriptor)(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
#endif
#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1))
uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
#endif
} USBD_DescriptorsTypeDef;
USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev,
USBD_DescriptorsTypeDef *pdesc, uint8_t id)
{
USBD_StatusTypeDef ret;
/* Check whether the USB Host handle is valid */
if (pdev == NULL)
{
#if (USBD_DEBUG_LEVEL > 1U)
USBD_ErrLog("Invalid Device handle");
#endif
return USBD_FAIL;
}
/* Unlink previous class resources */
pdev->pClass = NULL;
pdev->pUserData = NULL;
pdev->pConfDesc = NULL;
/* Assign USBD Descriptors */
if (pdesc != NULL)
{
pdev->pDesc = pdesc;
}
/* Set Device initial State */
pdev->dev_state = USBD_STATE_DEFAULT;
pdev->id = id;
/* Initialize low level driver */
ret = USBD_LL_Init(pdev);
return ret;
}
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
if (pdev->id == DEVICE_FS)
{
g_pcd_usb_otg_fs.pData = pdev; /* g_pcd_usb_otg_fs的pData指向pdev */
pdev->pData = &g_pcd_usb_otg_fs; /* pdev的pData指向g_pcd_usb_otg_fs */
g_pcd_usb_otg_fs.Instance = USB_OTG_FS; /* 使用USB OTG FS*/
g_pcd_usb_otg_fs.Init.dev_endpoints = 4; /* 端点数为4 */
g_pcd_usb_otg_fs.Init.speed = PCD_SPEED_FULL; /* USB全速(12Mbps) */
g_pcd_usb_otg_fs.Init.dma_enable = DISABLE; /* 不使能DMA */
g_pcd_usb_otg_fs.Init.phy_itface = PCD_PHY_EMBEDDED; /* 使用内部PHY */
g_pcd_usb_otg_fs.Init.Sof_enable = DISABLE; /* 不使能SOF中断 */
g_pcd_usb_otg_fs.Init.low_power_enable = DISABLE; /* 不使能低功耗模式 */
g_pcd_usb_otg_fs.Init.lpm_enable = DISABLE; /* 不使能连接电源管理 */
g_pcd_usb_otg_fs.Init.vbus_sensing_enable = DISABLE; /* 不使能VBUS检测 */
g_pcd_usb_otg_fs.Init.use_dedicated_ep1 = DISABLE; /* 禁止EP1 dedicated中断 */
HAL_PCD_Init(&g_pcd_usb_otg_fs);
HAL_PCDEx_SetRxFiFo(&g_pcd_usb_otg_fs, 0x80); /* 设置接收FIFO大小为0X80(128字节) */
HAL_PCDEx_SetTxFiFo(&g_pcd_usb_otg_fs, 0, 0x40); /* 设置发送FIFO 0的大小为0X40(64字节) */
HAL_PCDEx_SetTxFiFo(&g_pcd_usb_otg_fs, 1, 0x80); /* 设置发送FIFO 1的大小为0X80(128字节) */
}
return USBD_OK;
}
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
{
USB_OTG_GlobalTypeDef *USBx;
uint8_t i;
/* Check the PCD handle allocation */
if (hpcd == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
USBx = hpcd->Instance;
if (hpcd->State == HAL_PCD_STATE_RESET)
{
/* Allocate lock resource and initialize it */
hpcd->Lock = HAL_UNLOCKED;
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
hpcd->SOFCallback = HAL_PCD_SOFCallback;
hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
hpcd->ResetCallback = HAL_PCD_ResetCallback;
hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
if (hpcd->MspInitCallback == NULL)
{
hpcd->MspInitCallback = HAL_PCD_MspInit;
}
/* Init the low level hardware */
hpcd->MspInitCallback(hpcd);
#else
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
HAL_PCD_MspInit(hpcd);
#endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
}
hpcd->State = HAL_PCD_STATE_BUSY;
/* Disable DMA mode for FS instance */
if ((USBx->CID & (0x1U << 8)) == 0U)
{
hpcd->Init.dma_enable = 0U;
}
/* Disable the Interrupts */
__HAL_PCD_DISABLE(hpcd);
/*Init the Core (common init.) */
if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
{
hpcd->State = HAL_PCD_STATE_ERROR;
return HAL_ERROR;
}
/* Force Device Mode*/
(void)USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE);
/* Init endpoints structures */
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
{
/* Init ep structure */
hpcd->IN_ep[i].is_in = 1U;
hpcd->IN_ep[i].num = i;
hpcd->IN_ep[i].tx_fifo_num = i;
/* Control until ep is activated */
hpcd->IN_ep[i].type = EP_TYPE_CTRL;
hpcd->IN_ep[i].maxpacket = 0U;
hpcd->IN_ep[i].xfer_buff = 0U;
hpcd->IN_ep[i].xfer_len = 0U;
}
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
{
hpcd->OUT_ep[i].is_in = 0U;
hpcd->OUT_ep[i].num = i;
/* Control until ep is activated */
hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
hpcd->OUT_ep[i].maxpacket = 0U;
hpcd->OUT_ep[i].xfer_buff = 0U;
hpcd->OUT_ep[i].xfer_len = 0U;
}
/* Init Device */
if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
{
hpcd->State = HAL_PCD_STATE_ERROR;
return HAL_ERROR;
}
hpcd->USB_Address = 0U;
hpcd->State = HAL_PCD_STATE_READY;
#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
/* Activate LPM */
if (hpcd->Init.lpm_enable == 1U)
{
(void)HAL_PCDEx_ActivateLPM(hpcd);
}
#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
(void)USB_DevDisconnect(hpcd->Instance);
return HAL_OK;
}
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
{
GPIO_InitTypeDef gpio_init_struct = {0};
if (hpcd->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引脚 */
__HAL_RCC_USB_OTG_FS_CLK_ENABLE(); /* 使能OTG FS时钟 */
HAL_NVIC_SetPriority(OTG_FS_IRQn, 1, 0); /* 优先级设置为抢占1,子优先级0 */
HAL_NVIC_EnableIRQ(OTG_FS_IRQn); /* 使能OTG FS中断 */
}
else if (hpcd->Instance == USB_OTG_HS)
{
/* USB OTG HS本例程没用到,故不做处理 */
}
}
二、添加类
USBD_RegisterClass(&USBD_Device, USBD_CDC_CLASS); /* 添加类 */
#define USBD_CDC_CLASS &USBD_CDC
/* CDC interface class callbacks structure */
USBD_ClassTypeDef USBD_CDC =
{
USBD_CDC_Init,
USBD_CDC_DeInit,
USBD_CDC_Setup,
NULL, /* EP0_TxSent, */
USBD_CDC_EP0_RxReady,
USBD_CDC_DataIn,
USBD_CDC_DataOut,
NULL,
NULL,
NULL,
USBD_CDC_GetHSCfgDesc,
USBD_CDC_GetFSCfgDesc,
USBD_CDC_GetOtherSpeedCfgDesc,
USBD_CDC_GetDeviceQualifierDescriptor,
};
typedef struct _Device_cb
{
uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
/* Control Endpoints*/
uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev);
uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev);
/* Class Specific Endpoints*/
uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev);
uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
uint8_t *(*GetHSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetFSConfigDescriptor)(uint16_t *length);
uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length);
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length);
#endif
} USBD_ClassTypeDef;
USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
{
uint16_t len = 0U;
if (pclass == NULL)
{
#if (USBD_DEBUG_LEVEL > 1U)
USBD_ErrLog("Invalid Class handle");
#endif
return USBD_FAIL;
}
/* link the class to the USB Device handle */
pdev->pClass = pclass;
/* Get Device Configuration Descriptor */
#ifdef USE_USB_HS
if (pdev->pClass->GetHSConfigDescriptor != NULL)
{
pdev->pConfDesc = (void *)pdev->pClass->GetHSConfigDescriptor(&len);
}
#else /* Default USE_USB_FS */
if (pdev->pClass->GetFSConfigDescriptor != NULL)
{
pdev->pConfDesc = (void *)pdev->pClass->GetFSConfigDescriptor(&len);
}
#endif /* USE_USB_FS */
return USBD_OK;
}
三、添加回调函数
USBD_CDC_RegisterInterface(&USBD_Device, &USBD_CDC_fops); /* 为MSC类添加回调函数 */
/* 虚拟串口配置函数(供USB内核调用) */
USBD_CDC_ItfTypeDef USBD_CDC_fops =
{
CDC_Itf_Init,
CDC_Itf_DeInit,
CDC_Itf_Control,
CDC_Itf_Receive
};
typedef struct _USBD_CDC_Itf
{
int8_t (* Init)(void);
int8_t (* DeInit)(void);
int8_t (* Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length);
int8_t (* Receive)(uint8_t *Buf, uint32_t *Len);
int8_t (* TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum);
} USBD_CDC_ItfTypeDef;
uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,
USBD_CDC_ItfTypeDef *fops)
{
if (fops == NULL)
{
return (uint8_t)USBD_FAIL;
}
pdev->pUserData = fops;
return (uint8_t)USBD_OK;
}
四、开启USB
USBD_Start(&USBD_Device); /* 开启USB */
USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev)
{
/* Start the low level driver */
return USBD_LL_Start(pdev);
}
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
HAL_StatusTypeDef hal_status = HAL_OK;
USBD_StatusTypeDef usb_status = USBD_OK;
hal_status = HAL_PCD_Start(pdev->pData);
usb_status = USBD_Get_USB_Status(hal_status);
return usb_status;
}
USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
USBD_StatusTypeDef usb_status = USBD_OK;
switch (hal_status)
{
case HAL_OK :
usb_status = USBD_OK;
break;
case HAL_ERROR :
usb_status = USBD_FAIL;
break;
case HAL_BUSY :
usb_status = USBD_BUSY;
break;
case HAL_TIMEOUT :
usb_status = USBD_FAIL;
break;
default :
usb_status = USBD_FAIL;
break;
}
return usb_status;
}
五、延时
delay_ms(1800);
六、串口处理
while (1)
{
delay_ms(1);
if (usbstatus != g_device_state) /* USB连接状态发生了改变 */
{
usbstatus = g_device_state; /* 记录新的状态 */
if (usbstatus == 1)
{
lcd_show_string(30, 110, 200, 16, 16, "USB Connected ", RED); /* 提示USB连接成功 */
LED1(0); /* 绿灯亮 */
}
else
{
lcd_show_string(30, 110, 200, 16, 16, "USB disConnected ", RED); /* 提示USB断开 */
LED1(1); /* 绿灯灭 */
}
}
if (g_usb_usart_rx_sta & 0x8000)
{
len = g_usb_usart_rx_sta & 0x3FFF; /* 得到此次接收到的数据长度 */
usb_printf("\r\n您发送的消息长度为:%d\r\n\r\n", len);
cdc_vcp_data_tx(g_usb_usart_rx_buffer, len);
usb_printf("\r\n\r\n"); /* 插入换行 */
g_usb_usart_rx_sta = 0;
}
else
{
times++;
if (times % 5000 == 0)
{
usb_printf("\r\nSTM32开发板USB虚拟串口实验\r\n");
usb_printf("正点原子@ALIENTEK\r\n\r\n");
}
if (times % 200 == 0)
{
usb_printf("请输入数据,以回车键结束\r\n");
}
if (times % 30 == 0)
{
LED0_TOGGLE(); /* 闪烁LED,提示系统正在运行 */
}
delay_ms(10);
}
}
七、测试结果:


