/**
* @brief Configure the USB.
* @param None
* @retval None
*/
void USB_Config(void)
{
Set_System(); --------> 1
Set_USBClock(); --------> 2
USB_Interrupts_Config(); --------> 3
USB_Init(); --------> 4
// while (bDeviceState != CONFIGURED)
// {}
}
1. Set_System()
位于USB_Example\hw_config.c文件中。其主要功能是初始化单片机时钟系统、使能相关的外设电源。
/**
* @brief Configures Main system clocks & power.
* @param None
* @retval None
*/
void Set_System(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f30x.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f30x.c file
*/
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); --------> 1.1
/* Enable the SYSCFG module clock (used for the USB disconnect feature) */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); --------> 1.2
/* Enable the USB disconnect GPIO clock */
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIO_DISCONNECT, ENABLE);
/*Set PA11,12 as IN - USB_DM,DP*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); --------> 1.3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure); -------- 1.4
/*SET PA11,12 for USB: USB_DM,DP*/
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_14); --------> 1.5
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_14); --------> 1.5
#if defined(USB_USE_EXTERNAL_PULLUP)
/* Enable the USB disconnect GPIO clock */
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIO_DISCONNECT, ENABLE);
// /* USB_DISCONNECT used as USB pull-up */
// GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
// GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure);
#endif /* USB_USE_EXTERNAL_PULLUP */
/* Configure the EXTI line 18 connected internally to the USB IP */
EXTI_ClearITPendingBit(EXTI_Line18); --------> 1.6
EXTI_InitStructure.EXTI_Line = EXTI_Line18; /*USB resume from suspend mode*/
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); --------> 1.7
EXTI_ClearITPendingBit(USER_BUTTON_EXTI_LINE); --------> 1.6
}
1.1 RCC_APB1PeriphClockCmd()
位于USB_Example\Libraries\STM32F30x_StdPeriph_Driver\src\stm32f30x_rcc.c文件中。其主要功能是使能或者禁止外设时钟。
/**
* @brief Enables or disables the Low Speed APB (APB1) peripheral clock.
* @note After reset, the peripheral clock (used for registers read/write access)
* is disabled and the application software has to enable this clock before
* using it.
* @param RCC_APB1Periph: specifies the APB1 peripheral to gates its clock.
* This parameter can be any combination of the following values:
* @arg RCC_APB1Periph_TIM2
* @arg RCC_APB1Periph_TIM3
* @arg RCC_APB1Periph_TIM4
* @arg RCC_APB1Periph_TIM6
* @arg RCC_APB1Periph_TIM7
* @arg RCC_APB1Periph_WWDG
* @arg RCC_APB1Periph_SPI2
* @arg RCC_APB1Periph_SPI3
* @arg RCC_APB1Periph_USART2
* @arg RCC_APB1Periph_USART3
* @arg RCC_APB1Periph_UART4
* @arg RCC_APB1Periph_UART5
* @arg RCC_APB1Periph_I2C1
* @arg RCC_APB1Periph_I2C2
* @arg RCC_APB1Periph_USB
* @arg RCC_APB1Periph_CAN1
* @arg RCC_APB1Periph_PWR
* @arg RCC_APB1Periph_DAC
* @param NewState: new state of the specified peripheral clock.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB1ENR |= RCC_APB1Periph;
}
else
{
RCC->APB1ENR &= ~RCC_APB1Periph;
}
}
RCC在USB_Example\Libraries\CMSIS\Device\ST\STM32F30x\Include\stm32f30x.h中定义:
#define RCC ((RCC_TypeDef *) RCC_BASE)
RCC_BASE在同文件中定义:
#define RCC_BASE (AHB1PERIPH_BASE + 0x00001000)
AHB1PERIPH_BASE也在同文件中定义:
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
PERIPH_BASE也在同文件中定义:
#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
其中:
RCC_BASE展开来为(uint32_t)0x40000000 + 0x00020000 + 0x00001000,即(uint32_t)0x40021000,对应手册中P42中的RCC寄存器。
而RCC_TypeDef 在USB_Example\Libraries\CMSIS\Device\ST\STM32F30x\Include\stm32f30x.h中定义:
/**
* @brief Reset and Clock Control
*/
typedef struct
{
__IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */
__IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x04 */
__IO uint32_t CIR; /*!< RCC clock interrupt register, Address offset: 0x08 */
__IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x0C */
__IO uint32_t APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x10 */
__IO uint32_t AHBENR; /*!< RCC AHB peripheral clock register, Address offset: 0x14 */
__IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x18 */
__IO uint32_t APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x1C */
__IO uint32_t BDCR; /*!< RCC Backup domain control register, Address offset: 0x20 */
__IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x24 */
__IO uint32_t AHBRSTR; /*!< RCC AHB peripheral reset register, Address offset: 0x28 */
__IO uint32_t CFGR2; /*!< RCC clock configuration register 2, Address offset: 0x2C */
__IO uint32_t CFGR3; /*!< RCC clock configuration register 3, Address offset: 0x30 */
} RCC_TypeDef;
上面的结构体定义对应手册中P133中的7.4.14 RCC register map。
“1. Set_System()”中调用RCC_APB1PeriphClockCmd()时的第一个参数RCC_APB1Periph_PWR在USB_Example\Libraries\STM32F30x_StdPeriph_Driver\inc\stm32f30x_rcc.h中定义:
#define RCC_APB1Periph_PWR ((uint32_t)0x10000000)
对应手册P120中"Bit 28 PWREN: Power interface clock enable"。
综合以上内容可知,RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); --------> 1.1 所实现功能如其注释所述,使能电源时钟。