接上一篇文章。继续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()在其里边进行具体实现了。
欲知详情,且听下回分解。