STM32F303X单片机USB例程详细解析4



接上一篇文章。继续void Set_System(void)的分析。


1.4 GPIO_Init()

位于USB_Example\Libraries\STM32F30x_StdPeriph_Driver\src\stm32f30x_gpio.c文件中。其主要功能是根据传入的参数初始化GPIO外设。


/**
  * @brief  Initializes the GPIOx peripheral according to the specified
  *         parameters in the GPIO_InitStruct.
  * @param  GPIOx: where x can be (A, B, C, D, E or F) to select the GPIO peripheral.
  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that
  *         contains the configuration information for the specified GPIO
  *         peripheral.
  * @note   GPIO_Pin: selects the pin to be configured:
  *         GPIO_Pin_0->GPIO_Pin_15 for GPIOA, GPIOB, GPIOC, GPIOD and GPIOE;
  *         GPIO_Pin_0->GPIO_Pin_2, GPIO_Pin_4, GPIO_Pin_6, GPIO_Pin_9
  *                       and GPIO_Pin_10 for GPIOF.
  * @retval None
  */
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
  uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
  assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));

  /*-------------------------- Configure the port pins -----------------------*/
  /*-- GPIO Mode Configuration --*/
  for (pinpos = 0x00; pinpos < 0x10; pinpos++)
  {
    pos = ((uint32_t)0x01) << pinpos;

    /* Get the port pins position */
    currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;

    if (currentpin == pos)
    {
      if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF))
      {
        /* Check Speed mode parameters */
        assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));

        /* Speed mode configuration */
        GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2));
        GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2));

        /* Check Output mode parameters */
        assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType));

        /* Output mode configuration */
        GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos));
        GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos));
      }
     
      GPIOx->MODER  &= ~(GPIO_MODER_MODER0 << (pinpos * 2));

      GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));

      /* Pull-up Pull down resistor configuration */
      GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));
      GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));
    }
  }
}


先看传入参数,一个是GPIO_TypeDef *类型,一个是GPIO_InitTypeDef *类型。先看GPIO_TypeDef ,在USB_Example\Libraries\CMSIS\Device\ST\STM32F30x\Include\stm32f30x.h中定义。

/**
  * @brief General Purpose I/O
  */

typedef struct
{
  __IO uint32_t MODER;        /*!< GPIO port mode register,                                  Address offset: 0x00 */
  __IO uint16_t OTYPER;       /*!< GPIO port output type register,                           Address offset: 0x04 */
  uint16_t RESERVED0;         /*!< Reserved,                                                                 0x06 */
  __IO uint32_t OSPEEDR;      /*!< GPIO port output speed register,                          Address offset: 0x08 */
  __IO uint32_t PUPDR;        /*!< GPIO port pull-up/pull-down register,                     Address offset: 0x0C */
  __IO uint16_t IDR;          /*!< GPIO port input data register,                            Address offset: 0x10 */
  uint16_t RESERVED1;         /*!< Reserved,                                                                 0x12 */
  __IO uint16_t ODR;          /*!< GPIO port output data register,                           Address offset: 0x14 */
  uint16_t RESERVED2;         /*!< Reserved,                                                                 0x16 */
  __IO uint32_t BSRR;         /*!< GPIO port bit set/reset registerBSRR,                     Address offset: 0x18 */
  __IO uint32_t LCKR;         /*!< GPIO port configuration lock register,                    Address offset: 0x1C */
  __IO uint32_t AFR[2];       /*!< GPIO alternate function low register,                Address offset: 0x20-0x24 */
  __IO uint16_t BRR;          /*!< GPIO bit reset register,                                  Address offset: 0x28 */
  uint16_t RESERVED3;         /*!< Reserved,                                                                 0x2A */
}GPIO_TypeDef;

这个结构体与其说是结构体,其实是以结构体形式反映了芯片中寄存器的分布,对应手册中P151~152 8.4.12 GPIO register map。向其成员赋值,实际上就是写相应的寄存器。

GPIO_Init(GPIOA, &GPIO_InitStructure);  -------- 1.4 中传入的实参为GPIOA,在USB_Example\Libraries\CMSIS\Device\ST\STM32F30x\Include\stm32f30x.h中定义:

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)

GPIOA_BASE也在同文件中定义:

#define GPIOA_BASE            (AHB2PERIPH_BASE + 0x0000)

AHB2PERIPH_BASE也在同文件中定义:

#define AHB2PERIPH_BASE       (PERIPH_BASE + 0x08000000)

PERIPH_BASE也定义在同文件中:

#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */

因此,GPIOA展开来为:

0x40000000 + 0x08000000 + 0x0000 = 0x48000000

与手册中P48 AHB2部分对应,其中GPIOA正好位于AHB2的起始处,因此其基地址与AHB2基地址相同。

这个参数的意思是告诉GPIO_Init(),要设置的是GPIOA。


再看GPIO_InitTypeDef,在USB_Example\Libraries\STM32F30x_StdPeriph_Driver\inc\stm32f30x_gpio.h文件中定义。

/**
  * @brief  GPIO Init structure definition 
  */
typedef struct
{
  uint32_t GPIO_Pin;              /*!< Specifies the GPIO pins to be configured.
                                       This parameter can be any value of @ref GPIO_pins_define */
                                      
  GPIOMode_TypeDef GPIO_Mode;     /*!< Specifies the operating mode for the selected pins.
                                       This parameter can be a value of @ref GPIOMode_TypeDef   */

  GPIOSpeed_TypeDef GPIO_Speed;   /*!< Specifies the speed for the selected pins.
                                       This parameter can be a value of @ref GPIOSpeed_TypeDef  */

  GPIOOType_TypeDef GPIO_OType;   /*!< Specifies the operating output type for the selected pins.
                                       This parameter can be a value of @ref GPIOOType_TypeDef  */

  GPIOPuPd_TypeDef GPIO_PuPd;     /*!< Specifies the operating Pull-up/Pull down for the selected pins.
                                       This parameter can be a value of @ref GPIOPuPd_TypeDef   */
}GPIO_InitTypeDef;

这个结构体其实是将GPIO_TypeDef结构体中的几个成员(MODER、OTYPER、OSPEEDR、PUPDR)单独提出来,为了方便设置。

GPIOMode_TypeDef、GPIOSpeed_TypeDef、GPIOOType_TypeDef、GPIOPuPd_TypeDef 都在USB_Example\Libraries\STM32F30x_StdPeriph_Driver\inc\stm32f30x_gpio.h中定义:


/** @defgroup Configuration_Mode_enumeration
  * @{
  */
typedef enum
{
  GPIO_Mode_IN   = 0x00, /*!< GPIO Input Mode */
  GPIO_Mode_OUT  = 0x01, /*!< GPIO Output Mode */
  GPIO_Mode_AF   = 0x02, /*!< GPIO Alternate function Mode */
  GPIO_Mode_AN   = 0x03  /*!< GPIO Analog In/Out Mode      */
}GPIOMode_TypeDef;


/** @defgroup Output_Maximum_frequency_enumeration
  * @{
  */
typedef enum
{
  GPIO_Speed_Level_1  = 0x01, /*!< Fast Speed     */
  GPIO_Speed_Level_2  = 0x02, /*!< Meduim Speed   */
  GPIO_Speed_Level_3  = 0x03  /*!< High Speed     */
}GPIOSpeed_TypeDef;


/** @defgroup Output_type_enumeration
  * @{
  */
typedef enum
{
  GPIO_OType_PP = 0x00,
  GPIO_OType_OD = 0x01
}GPIOOType_TypeDef;


/** @defgroup Configuration_Pull-Up_Pull-Down_enumeration
  * @{
  */
typedef enum
{
  GPIO_PuPd_NOPULL = 0x00,
  GPIO_PuPd_UP     = 0x01,
  GPIO_PuPd_DOWN   = 0x02
}GPIOPuPd_TypeDef;


以上几个枚举分别对应手册中的 8.4.1 GPIO port mode register、8.4.3 GPIO port output speed register、 8.4.2 GPIO port output type register、8.4.4 GPIO port pull-up/pull-down register。

结合void Set_System(void)中的代码(见STM32F303X单片机USB例程详细解析1):

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;

可知是要将GPIOA的11、12脚配置为:

High Speed(50MHZ);

GPIO Alternate function Mode;

Output push/pull;

No pull-up,pull-down

现在GPIO以及要设置的数据已经准备好,就等GPIO_Init()在其里边进行具体实现了。

欲知详情,且听下回分解。


发布了34 篇原创文章 · 获赞 12 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/50323323