单片机USB虚拟串口实验
单片机 STM32F407开发板DMF407电机开发板平台keil V5.31HSE 为8MHZHSI为16MHZ一、初始化USBUSBD_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; }四、开启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); } }七、测试结果