GPIO的庫函數


 

1 void GPIO_DeInit(GPIO_TypeDef* GPIOx)

這個函數調用了rcc.c里面的RCC_AHB1PeriphResetCmd,對外設端口進行復位,最終操作的是RCC_AHB1RSTR和RCC_AHB2RSTR,這樣操作后,使端口寄存器恢復默認值
void GPIO_DeInit(GPIO_TypeDef* GPIOx)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  if (GPIOx == GPIOA)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE); //復位端口
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE);//不復位
  }
  else if (GPIOx == GPIOB)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, DISABLE);
  }
  else if (GPIOx == GPIOC)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, DISABLE);
  }
  else if (GPIOx == GPIOD)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, DISABLE);
  }
  else if (GPIOx == GPIOE)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, DISABLE);
  }
  else if (GPIOx == GPIOF)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, DISABLE);
  }
  else if (GPIOx == GPIOG)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, DISABLE);
  }
  else if (GPIOx == GPIOH)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, DISABLE);
  }

  else if (GPIOx == GPIOI)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, DISABLE);
  }
  else if (GPIOx == GPIOJ)
  {
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOJ, ENABLE);
    RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOJ, DISABLE);
  }
  else
  {
    if (GPIOx == GPIOK)
    {
      RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOK, ENABLE);
      RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOK, DISABLE);
    }
  }
}

2  這個函數傳入的參數是GPIO_TypeDef和GPIO_InitStruct,GPIO_TypeDef是一個數組,包含了所有GPIO相關的寄存器。GPIO_InitTypeDef也是一個數組,包含了對GPIO的具體配置選項,比如輸入輸出選擇等等。

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
  uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
  // 參數檢查
  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));

  for (pinpos = 0x00; pinpos < 0x10; pinpos++) //從第0個pin開始掃描要賦值哪個pin
  {
    pos = ((uint32_t)0x01) << pinpos;
    /* Get the port pins position */
    currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; //GPIO_InitStruct->GPIO_Pin會確定GPIOX端口中具體哪個管腳被初始化

    if (currentpin == pos) //掃描到了需要初始化的管腳,進行配置
    { //現在GPIOX是一個指向GPIO_TypeDef的指針,那么GPIO->就是在操作moder寄存器
      GPIOx->MODER  &= ~(GPIO_MODER_MODER0 << (pinpos * 2)); // 把這個要配置的pin對於的moder寄存器的兩位清零
      GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));//把相應的配置寫入寄存器

      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)); //這里和moder寄存器的配置是一樣的
        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));
           //配置輸出或者推挽,一個bit對應一個pin,所以不需要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)); // 配置上下拉
    }
  }
}

這個函數的調用方法如下所示:

void myGPIO_Init(void)
{         
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能F端口的時鍾//GPIOF9,F10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//選擇需要配置的管腳。GPIO_Pin_9的值被定義成0x0200
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;// 配置成輸出
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;// 配置成push-pull
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//配置成上拉
  GPIO_Init(GPIOF, &GPIO_InitStructure);// 調用上面這個初始化函數

}

以上有很多例如:GPIO_Pin_9 ,GPIO_Mode_OUT,都是定義在stm32f4xx_gpio.h的枚舉類的值。以上這個函數,把各種值賦給GPIO_InitTypeDef類型的GPIO_InitStructure數組,然后調用GPIO_Init這個函數,把這些設置寫入寄存器。GPIOF是F端口的寄存器基地址。

3.void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)

這個函數和上面這個調用類似,是把這些GPIO寄存器恢復默認值

void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
{
  /* Reset GPIO init structure parameters values */
  GPIO_InitStruct->GPIO_Pin  = GPIO_Pin_All;
  GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStruct->GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL;
}

4.void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

端口配置鎖定寄存器,傳入的參數的哪個端口,哪個管腳,具體見GPIOx_LCKR寄存器。是用來鎖定管腳的配置,這個寄存器低16位是具體某個管腳的鎖定使能。LCKK管腳是總的鎖定激活。這里的5步操作,在手冊中是由規定的:“鎖定鍵寫序列”

void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  __IO uint32_t tmp = 0x00010000;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  tmp |= GPIO_Pin;
  /* Set LCKK bit */
  GPIOx->LCKR = tmp;
  /* Reset LCKK bit */
  GPIOx->LCKR =  GPIO_Pin;
  /* Set LCKK bit */
  GPIOx->LCKR = tmp;
  /* Read LCKK bit*/
  tmp = GPIOx->LCKR;
  /* Read LCKK bit*/
  tmp = GPIOx->LCKR;
}

 5. uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

   這個函數其實是讀IDR寄存器,即管腳的輸入值

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  uint8_t bitstatus = 0x00;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

  if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET) //IDR寄存器中,需要讀的這個管腳如果不是0
  {
    bitstatus = (uint8_t)Bit_SET;
  }
  else
  {
    bitstatus = (uint8_t)Bit_RESET;
  }
  return bitstatus;
}

6、uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)

 這個函數是讀16比特

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  return ((uint16_t)GPIOx->IDR);
}

7、uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

這個函數是讀ODR寄存器,即輸出的值,可以看GPIO的結構,輸出也是可以讀的。

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  uint8_t bitstatus = 0x00;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

  if (((GPIOx->ODR) & GPIO_Pin) != (uint32_t)Bit_RESET)
  {
    bitstatus = (uint8_t)Bit_SET;
  }
  else
  {
    bitstatus = (uint8_t)Bit_RESET;
  }
  return bitstatus;

8、uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)

類似,這里讀16比特

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  return ((uint16_t)GPIOx->ODR);
}

9、void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

寫1

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  GPIOx->BSRRL = GPIO_Pin;
}

 

10、void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

寫0

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  GPIOx->BSRRH = GPIO_Pin;
}

11、void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)

把GPIO的某一位寫0或者寫1

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
  assert_param(IS_GPIO_BIT_ACTION(BitVal));

  if (BitVal != Bit_RESET)
  {
    GPIOx->BSRRL = GPIO_Pin;
  }
  else
  {
    GPIOx->BSRRH = GPIO_Pin ;
  }
}

12、void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)

對某個端口16位賦值

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  GPIOx->ODR = PortVal;
}

13、void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

對某個端口的值進行取反

void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  GPIOx->ODR ^= GPIO_Pin;
}

14、void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)

配置GPIO的復用功能,具體見AFRL和AFRH寄存器

void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
{
  uint32_t temp = 0x00;
  uint32_t temp_2 = 0x00;
  
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  assert_param(IS_GPIO_AF(GPIO_AF));
  //每個管腳的AF配置,在寄存器中都占了4位
  temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;//表示移到這兩個寄存器中的哪個4位
  GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;//先清零
//AFR有兩個寄存器,AFR[GPIO-PinSource>>0x03]確定哪個寄存器

temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp; //把寄存器中需要賦值的幾個bit賦值
GPIOx
->AFR[GPIO_PinSource >> 0x03] = temp_2; //寫入需要的值
}

調用方式如下:

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1)
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1)

不是所有的管腳,可以復用成任意的管腳,PA9和PA10有如下說明。可以看到PA9和USART1_TX,PA10是USART1_RX。

PA9:TIM1_CH2, USART1_TX,LCD_COM1, TIM15_BKIN,EVENTOU
PA10:TIM1_CH3, USART1_RX,OTG_FS_ID, LCD_COM2,TIM17_BKIN, EVENTOUT

另外還需要說明的是,這幾個接口,定義的AF的配置都是7,都是一樣的。但是某個管腳是限定成哪個接口的,所以不會搞錯。即把PA9和PA10的AF配置成7.是不會映射到USART2去的。同時,不同的USART對應不同的寄存器偏移地址。

#define GPIO_AF_USART1         ((uint8_t)0x07)  /* USART1 Alternate Function mapping  */
#define GPIO_AF_USART2         ((uint8_t)0x07)  /* USART2 Alternate Function mapping  */
#define GPIO_AF_USART3         ((uint8_t)0x07)  /* USART3 Alternate Function mapping  */
#define GPIO_AF7_SPI3          ((uint8_t)0x07)  /* SPI3/I2S3ext Alternate Function mapping */

 




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM