STM32库函数中GPIO_Init的理解

来源:互联网 发布:东珈网络精英 编辑:程序博客网 时间:2024/05/17 06:24

STM32中GPIO的配置风格需要理解一下。

 

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位,仔细研究GPIO_Init()函数后,确定为ST开发人员加上去的标识位。0x1_的是输出标识,其他则为输入模式。

下面看一下GPIO_Init()这个函数:

void GPIO_Init(GPIO_TypeDef*GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

{

  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)//判断是否为输出,0x1_

  {

    /* 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; //读出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; //pos*4,因为每个引脚配置占4位

        /* Clear the corresponding low controlregister bits

        pinmask = ((uint32_t)0x0F) <<pos;

        tmpreg &= ~pinmask; //把需要配置引脚的4位清0,其位不变

        /* Write the mode configuration in thecorresponding bits

        tmpreg |= (currentmode << pos);//把配置数据写入tmpreg

        /* Reset the corresponding ODR bit //如果是下拉输入或者上拉输入,则还需要配置PxODR位

        if (GPIO_InitStruct->GPIO_Mode ==GPIO_Mode_IPD)

        {

          GPIOx->BRR = (((uint32_t)0x01)<< pinpos); //如果下拉,清除对应ODRy为0

        }

        else

        {

          /* Set the corresponding ODR bit

          if (GPIO_InitStruct->GPIO_Mode ==GPIO_Mode_IPU)

          {

            GPIOx->BSRR = (((uint32_t)0x01)<< pinpos); //如果上拉,设置对应的ODRy为1

          }

        }

      }

    }

    GPIOx->CRL = tmpreg; //把配置好的数值写入寄存器

  }

0 0