原创 STM32下的GPIO.c的GPIO_Init及模式理解

2009-11-30 21:10 5621 4 4 分类: MCU/ 嵌入式
看了下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条评论)

登录后参与讨论
我要评论
0
4
关闭 站长推荐上一条 /2 下一条