原创
STM32下的GPIO.c的GPIO_Init及模式理解
看了下stm32f10x_gpio.h下的模式定义如下:
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
感觉不对呀,配置一个引脚只需要4位寄存器,而这里确定义使用了8位,所以感觉应该是人为加上的标识位。细读了stm32f10x_gpio.c的GPIO_Init之后发现,果然一致。此处的高4位为标识为,0x1x为输出标识,而不是输出的则是输入模式。
接着将此函数注释写出来,凭自己的感觉,但总的感觉来说,库函数过于复杂,至少这个函数好像是,也许以后可以写出个更简单有效的。
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
/*---------------------------- GPIO Mode Configuration -----------------------*/
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); //屏蔽附加的标志识别位
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) //根据定义判断是否为输出,由附加识别位0x1x
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; //输出的情况下赋予输出速度模式
}
/*---------------------------- GPIO CRL Configuration ------------------------*/
/* Configure the eight low port pins */
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00) //判断引脚是否有效
{
tmpreg = GPIOx->CRL; //读出原寄存器内容,并保存
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; //先找出最低需要配置的引脚
if (currentpin == pos)
{
pos = pinpos << 2; //左移两位相当于乘4,因为每位配置占用四位。
/* Clear the corresponding low control register bits */
pinmask = ((uint32_t)0x0F) << pos;//将0x0f左移引脚数乘4的值
tmpreg &= ~pinmask; //将屏蔽值取反,将当前所需配置的位的配置值清零,并与原寄存器内容
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos); //将所需要配置成的模式赋予临时变量
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos); //如果为下拉,则需要将输出寄存器配置为0
}
else
{
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos); //如果为上拉,则需要将输出寄存器配置为1
}
}
}
}
GPIOx->CRL = tmpreg;
}
文章评论(0条评论)
登录后参与讨论