我在使用Keil-v5版本开发STM32F103RCT6型号的MCU的USB时遇见一个问题,在此请教下。
使用RTE开发的话,在RTE_Device.h中有一个USB Device Full Speed的配置项
其中的CON On/Off Pin设置看描述是用来驱动USB的D+ pull up
我勾选后设置active state = high,Port = GPIOA, Bit = 8(和硬件一致)
问题来了,为什么以上设置不起作用?板子上电后PC没有反应,USB口没有驱动起来
而在程序中直接使用以下代码就可以?
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_SetBits(GPIOA, GPIO_Pin_8);
stm32F103必须通过控制IO口电平间接控制外部的三极管或mos管来进行usb数据线的上下拉 stm32F2或stm32F4不存在该问题,所以不占用多余两个IO口 最好先检查一下usb线,是否是好的 没有看过你的RTE,如果只是定义,但没有调用IO响应功能,也没有作用。
经过这两天的查找,算是找到了原因:
一 硬件连接 GPIOA.8做上拉信号输出口,接了1个1K的电阻到GPIOA.12(即USBDP信号)
二 RTE_Device.h中通过Configuration Wizard界面可以配置USB的上拉信号
对应的代码在文件中也能看到// <e> USB Device Full-speed // <i> Configuration settings for Driver_USBD0 in component ::Drivers:USB Device #define RTE_USB_DEVICE 1 // <e> CON On/Off Pin // <i> Configure Pin for driving D+ pull-up // <i> GPIO Pxy (x = A..G, y = 0..15) // <o1> Active State <0=>Low <1=>High // <i> Selects Active State Logical Level // <o2> Port <0=>GPIOA <1=>GPIOB <2=>GPIOC <3=>GPIOD // <4=>GPIOE <5=>GPIOF <6=>GPIOG // <i> Selects Port Name // <o3> Bit <0-15> // <i> Selects Port Bit // </e> #define RTE_USB_DEVICE_CON_PIN 1 #define RTE_USB_DEVICE_CON_ACTIVE 1 #define RTE_USB_DEVICE_CON_PORT GPIO_PORT(0) #define RTE_USB_DEVICE_CON_BIT 8 // </e>
问题来了,在USBD_STM32F10x.c文件中的USBD_HW_Initialize函数代码如下:
/** \fn ARM_USBD_STATUS USBD_Initialize (ARM_USBD_SignalDeviceEvent_t cb_device_event, ARM_USBD_SignalEndpointEvent_t cb_endpoint_event) \brief Initialize USB Device Interface. \param[in] cb_device_event Pointer to \ref USBD_SignalDeviceEvent \param[in] cb_endpoint_event Pointer to \ref USBD_SignalEndpointEvent \return \ref USBD_STATUS */ static ARM_USBD_STATUS USBD_HW_Initialize (ARM_USBD_SignalDeviceEvent_t cb_device_event, ARM_USBD_SignalEndpointEvent_t cb_endpoint_event) { #if (RTE_USB_DEVICE) cbDeviceEvent = cb_device_event; cbEndpointEvent = cb_endpoint_event; #if (RTE_USB_DEVICE_CON_PIN) // Configure CON pin (controls pull-up on D+ line) GPIO_PortClock (RTE_USB_DEVICE_CON_PORT, true); GPIO_PinWrite (RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, !RTE_OTG_FS_VBUS_ACTIVE); if (!GPIO_PinConfigure(RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, GPIO_OUT_OPENDRAIN, GPIO_MODE_OUT10MHZ)) return ARM_USBD_ERROR; #endif RCC->APB1ENR |= RCC_APB1ENR_USBEN; // Enable USB Device clock RCC->APB1RSTR |= RCC_APB1RSTR_USBRST; // Reset USB Device osDelay(1); // Wait 1 ms RCC->APB1RSTR &= ~RCC_APB1RSTR_USBRST; // Reset USB Device #endif return ARM_USBD_OK; }
另外还有对应的USBD_HW_DeviceConnect()函数,代码如下:
/** \fn ARM_USBD_STATUS USBD_HW_DeviceConnect (void) \brief Connect USB Device. \return \ref ARM_USBD_STATUS */ static ARM_USBD_STATUS USBD_HW_DeviceConnect (void) { // Soft connect GPIO_PinWrite (RTE_USB_DEVICE_CON_PORT, RTE_USB_DEVICE_CON_BIT, RTE_OTG_FS_VBUS_ACTIVE); CNTR = CNTR_FRES; // Force USB Reset CNTR = 0; ISTR = 0; // Clear Interrupt Status CNTR = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM; // USB Interrupt Mask return ARM_USBD_OK; }
在Initialize函数中,GPIO配置的模式是GPIO_OUT_OPENDRAIN模式,即GPIO是开漏模式。 同时在Initialize和Connect函数中,GPIO_PinWrite()函数使用的参数都是RTE_OTG_FS_VBUS_ACTIVE!
后果就是当执行完毕 USBD_Initialize (0); /* USB Device 0 Initialization */ USBD_Connect (0); 代码后,USBDP信号还是没有拉高,这样主机就检测不到USB设备的插入。
对于这个问题,RTE配置为GPIO_OUT_OPENDRAIN模式可以理解,毕竟硬件设计不同(我也不了解硬件,大牛可以分析下)。但是对于使用RTE_OTG_FS_VBUS_ACTIVE做参数配置没有任何道理吧? 我认为应该是RTE_USB_DEVICE_CON_ACTIVE,RTE这个地方不知道是错误还是有别的含义,也希望大牛能分析下
|