【STM32】開發板學習1 NUCLEO-L476RG:GPIO例程 點亮LED2燈

一、芯片以及開發板

1.芯片:STM32L476 

1.開發板:Nuleo-L476RG

官網查看詳細信息以及下載各種用戶手冊、說明書等等......

https://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-mpu-eval-tools/stm32-mcu-mpu-eval-tools/stm32-nucleo-boards/nucleo-l476rg.html#resource

 

3、GPIO示例參考資料

https://www.yiboard.com/thread-430-1-1.html

https://www.yiboard.com/thread-433-1-1.html

二、點燈前準備工作:

0.到官網找相應板子的驅動程序,下載安裝ST-Link V2-1

1.下載STM32CubeMX(STM32芯片圖形化配置工具,允許用戶使用圖形化嚮導生成C初始化代碼,可以大大減輕開發工作、時間和費用),創建工程,選擇芯片型號等

                                                                                                                                  2.Keil5 點擊工具欄的Pack Installer圖標,安裝STM32L4xx_DFP設備支持包,導入工程  ,通電,燈亮。

三、工程示例分析                                                                       

1.STM32CubeMX下載的示例工程,已將除用戶代碼的功能全部寫好,我們只需要在main.c中添加我們想讓板子跑的程序就OK。這裏我們要點亮一個LED2燈。

關於HAL庫的介紹:https://blog.csdn.net/m0_37621078/article/details/100084448

查看開發板用戶手冊:有3個LED燈,LD1常亮,LD2是user LED,LD3亮紅色說明開發板有電源5V。

2.查看開發板的原理圖:

(1)user按鍵,B1,與PC13相連

(2)LD2 ,也就是LED2燈,與PA5相連

 

四、點亮LD2

1.使用GPIO的第一步是使能時鐘:

該功能通過RCC(Reset and clock control)寄存器控制。所有的GPIO連接到AHB2總線。HAL庫提供了專門的函數來啓用GPIOA的時鐘。

__HAL_RCC_GPIOA_CLK_ENABLE

該函數定義可在文件stm32l4xx_hal_rcc.h找到,其實現函數如下:

 

 

通過實現函數可知,主要方式是通過RCC_AHB2ENR寄存器的第0位(GPIOA EN)置位來實現。

2.定義一個GPIO_InitTypeDef結構體來設置GPIO的參數

GPIO_InitTypeDef  GPIO_InitStruct;

結構體聲明在:stm3214xx_hal_gpio.h

 

該結構體有5個參數:

1. Pin 選擇引腳編號

2. Mode 設置GPIO的工作模式

3. Pull 設置引腳的上拉/下拉

4. Speed 設置GPIO輸出的最大頻率

5. Alternate 設置選擇引腳的複用功能

其中每項都有自己的選項

■  Pin:指定需要配置的GPIO管腳,該選項可以是以下的任何值:

   ■  GPIO_PIN_0:  選擇引腳0;

   ■  GPIO_PIN_1: 選擇引腳1;

   ■  GPIO_PIN_2:  選擇引腳2;

   ■  GPIO_PIN_3:  選擇引腳3;

   ■  GPIO_PIN_4:  選擇引腳4;

   ■  GPIO_PIN_5:  選擇引腳5;

   ■  GPIO_PIN_6:  選擇引腳6;

   ■  GPIO_PIN_7:  選擇引腳7;

   ■  GPIO_PIN_8:  選擇引腳8;

   ■  GPIO_PIN_9:  選擇引腳9;

   ■  GPIO_PIN_10:  選擇引腳10;

   ■  GPIO_PIN_11:  選擇引腳11;

   ■  GPIO_PIN_12:  選擇引腳12;

   ■  GPIO_PIN_13:  選擇引腳13;

   ■  GPIO_PIN_14:  選擇引腳14;

   ■  GPIO_PIN_15:  選擇引腳15;

   ■  GPIO_PIN_All: 選擇所有的引腳;

   ■  GPIO_PIN_MASK:引腳掩碼;

■  Mode:指定選擇引腳的工作模式

   ■  GPIO_MODE_INPUT:懸浮輸入模式

   ■  GPIO_MODE_OUTPUT_PP:推輓輸出模式

   ■  GPIO_MODE_OUTPUT_OD:漏極開路輸出模式

   ■  GPIO_MODE_AF_PP:複用功能推輓模式

   ■  GPIO_MODE_AF_OD:複用功能漏極開路模式

   ■  GPIO_MODE_ANALOG:模擬模式

   ■  GPIO_MODE_ANALOG_ADC_CONTROL:模擬模式,用於ADC轉換

   ■  GPIO_MODE_IT_RISING:上升沿觸發檢測的外部中斷模式

   ■  GPIO_MODE_IT_FALLING:下降沿觸發檢測的外部中斷模式

   ■  GPIO_MODE_IT_RISING_FALLING:上升/下降沿觸發檢測的外部中斷模式

   ■  GPIO_MODE_EVT_RISING:上升沿觸發檢測的外部事件模式

   ■  GPIO_MODE_EVT_FALLING:下降沿觸發檢測的外部事件模式

   ■  GPIO_MODE_EVT_RISING_FALLING:上升/下降沿觸發檢測的外部事件模式

   ■  Pull:指定引腳的上拉/下拉

   ■  GPIO_NOPULL:無上拉/下拉電阻

   ■  GPIO_PULLUP:帶有上拉電阻

   ■  GPIO_PULLDOWN:帶有下拉電阻

■  Speed:指定引腳的輸出頻率:

    ■  GPIO_SPEED_FREQ_LOW:輸出頻率最大爲5MHz

    ■  GPIO_SPEED_FREQ_MEDIUM:輸出頻率範圍5MHz-25MHz   

    ■  GPIO_SPEED_FREQ_HIGH:輸出頻率範圍25MHz-50MHz

    ■  GPIO_SPEED_FREQ_VERY_HIGH::輸出頻率範圍50MHz-80MHz

3.HAL庫提供了GPIO的初始化函數HAL_GPIO_Init()   ,函數在stm32l4xx_hal_gpio.h

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)

該頭文件的對應的.c文件中,有函數實現....en  看不懂

/**
  * @brief  Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init.
  * @param  GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family
  * @param  GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
  *         the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
  uint32_t position = 0x00u;
  uint32_t iocurrent;
  uint32_t temp;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
  assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
  assert_param(IS_GPIO_PULL(GPIO_Init->Pull));

  /* Configure the port pins */
  while (((GPIO_Init->Pin) >> position) != 0x00u)
  {
    /* Get current io position */
    iocurrent = (GPIO_Init->Pin) & (1uL << position);

    if (iocurrent != 0x00u)
    {
      /*--------------------- GPIO Mode Configuration ------------------------*/
      /* In case of Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
      {
        /* Check the Alternate function parameters */
        assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
        assert_param(IS_GPIO_AF(GPIO_Init->Alternate));

        /* Configure Alternate function mapped with the current IO */
        temp = GPIOx->AFR[position >> 3u];
        temp &= ~(0xFu << ((position & 0x07u) * 4u));
        temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));
        GPIOx->AFR[position >> 3u] = temp;
      }

      /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
      temp = GPIOx->MODER;
      temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
      temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
      GPIOx->MODER = temp;

      /* In case of Output or Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
         (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
      {
        /* Check the Speed parameter */
        assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
        /* Configure the IO Speed */
        temp = GPIOx->OSPEEDR;
        temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
        temp |= (GPIO_Init->Speed << (position * 2u));
        GPIOx->OSPEEDR = temp;

        /* Configure the IO Output Type */
        temp = GPIOx->OTYPER;
        temp &= ~(GPIO_OTYPER_OT0 << position) ;
        temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4u) << position);
        GPIOx->OTYPER = temp;
      }

#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)

      /* In case of Analog mode, check if ADC control mode is selected */
      if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG)
      {
        /* Configure the IO Output Type */
        temp = GPIOx->ASCR;
        temp &= ~(GPIO_ASCR_ASC0 << position) ;
        temp |= (((GPIO_Init->Mode & ANALOG_MODE) >> 3) << position);
        GPIOx->ASCR = temp;
      }

#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */

      /* Activate the Pull-up or Pull down resistor for the current IO */
      temp = GPIOx->PUPDR;
      temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
      temp |= ((GPIO_Init->Pull) << (position * 2u));
      GPIOx->PUPDR = temp;

      /*--------------------- EXTI Mode Configuration ------------------------*/
      /* Configure the External Interrupt or event for the current IO */
      if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
      {
        /* Enable SYSCFG Clock */
        __HAL_RCC_SYSCFG_CLK_ENABLE();

        temp = SYSCFG->EXTICR[position >> 2u];
        temp &= ~(0x0FuL << (4u * (position & 0x03u)));
        temp |= (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)));
        SYSCFG->EXTICR[position >> 2u] = temp;

        /* Clear EXTI line configuration */
        temp = EXTI->IMR1;
        temp &= ~(iocurrent);
        if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
        {
          temp |= iocurrent;
        }
        EXTI->IMR1 = temp;

        temp = EXTI->EMR1;
        temp &= ~(iocurrent);
        if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
        {
          temp |= iocurrent;
        }
        EXTI->EMR1 = temp;

        /* Clear Rising Falling edge configuration */
        temp = EXTI->RTSR1;
        temp &= ~(iocurrent);
        if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
        {
          temp |= iocurrent;
        }
        EXTI->RTSR1 = temp;

        temp = EXTI->FTSR1;
        temp &= ~(iocurrent);
        if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
        {
          temp |= iocurrent;
        }
        EXTI->FTSR1 = temp;
      }
    }

    position++;
  }
}

 

4.使用庫函數,點亮LD2

int main(void)
{
  /* USER CODE BEGIN 1 */
				//定義一個GPIO結構體 
	      GPIO_InitTypeDef GPIO_InitDef;
        
        //啓用GPIOA時鐘
        __HAL_RCC_GPIOA_CLK_ENABLE();

        //定義LD2的每一個參數 init配置
        GPIO_InitDef.Pin = GPIO_PIN_5;
        GPIO_InitDef.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitDef.Pull = GPIO_NOPULL;
        GPIO_InitDef.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitDef);

        //user按鍵的設置
        /*
        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitDef.Pin = GPIO_PIN_13;
        GPIO_InitDef.Mode = GPIO_MODE_INPUT;
        GPIO_InitDef.Pull = GPIO_PULLDOWN;
        GPIO_InitDef.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        //Initialize pins
        HAL_GPIO_Init(GPIOC, &GPIO_InitDef);
        */

        while (1) 
        {
				  //點亮LD2
          HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
        }

}

編譯、無報錯、load到開發板中,這樣,開發板的LED2就點亮了。

回顧電路板的原理圖:

我們要點亮LD2,所以要給PA5引腳接高電平。

如何給?HAL庫中給出了很多生成的代碼,代碼的做法是:將GPIO端分組,分爲ABCDEFG...等幾個組,然後再用引腳1234567...確定。所以寫的代碼爲:

 GPIO_InitDef.Pin = GPIO_PIN_5;
 HAL_GPIO_Init(GPIOA, &GPIO_InitDef);

先給結構體確定好引腳5,再規定這是A組的,就設置完一個結構體,也就是設置完一個LD2的參數。

五、關於GPIO結構體中的工作模式 GPIO_InitTypeDef ->Mode

1.這次點亮LED的工作模式爲推輓輸出:

推輓輸出:意思就是輸出具有驅動能力(比如:引腳上接一個LED,可以直接點亮,若是開漏輸出,就不能點亮LED)。

推輓輸出這個功能是比較常用的功能,我們一般輸出控制某個信號,基本上都是配置爲GPIO_Mode_Out_PP 推輓輸出。

推輓輸出電流大小也是比較關鍵的一個參數,根據芯片不同,其大小也不同,具體可以查看數據手冊:

參考鏈接:https://blog.csdn.net/ybhuangfugui/article/details/52953533

 

1、上拉輸入:上拉就是把電位拉高,比如拉到Vcc。上拉就是將不確定的信號通過一個電阻嵌位在高電平!電阻同時起限流作用!強弱只是上拉電阻的阻值不同,沒有什麼嚴格區分。

2、下拉輸入:就是把電壓拉低,拉到GND。與上拉原理相似。

3、浮空輸入:浮空(floating)就是邏輯器件的輸入引腳即不接高電平,也不接低電平。由於邏輯器件的內部結構,當它輸入引腳懸空時,相當於該引腳接了高電平。一般實際運用時,引腳不建議懸空,易受干擾。 通俗講就是讓管腳什麼都不接,浮空着。

4、模擬輸入:模擬輸入是指傳統方式的輸入。數字輸入是輸入PCM數字信號,即0,1的二進制數字信號,通過數模轉換,轉換成模擬信號,經前級放大進入功率放大器,功率放大器還是模擬的。

5、推輓輸出:可以輸出高,低電平,連接數字器件;推輓結構一般是指兩個三極管分別受兩互補信號的控制,總是在一個三極管導通的時候另一個截止。高低電平由IC的電源低定。

6、開漏輸出:輸出端相當於三極管的集電極。要得到高電平狀態需要上拉電阻纔行,適合於做電流型的驅動,其吸收電流的能力相對強(一般20mA以內)。

7、複用輸出:可以理解爲GPIO口被用作第二功能時的配置情況(即並非作爲通用IO口使用)。端口必須配置成複用功能輸出模式(推輓或開漏)。

好好理解一下,其實就能得出,這些GPIO模式能在下面幾種情況應用,參考網上的資料後,總結出下面幾點:
在STM32中選用IO模式,下面是參考網上的資料後總結出的結果。
(1)GPIO_Mode_AIN 模擬輸入—應用ADC模擬輸入,或者低功耗下省電

(2)GPIO_Mode_IN_FLOATING 浮空輸入—可以做KEY識別

(3)GPIO_Mode_IPD 下拉輸入— IO內部下拉電阻輸入

(4)GPIO_Mode_IPU 上拉輸入—IO內部上拉電阻輸入

(5)GPIO_Mode_Out_OD 開漏輸出—IO輸出0接GND,IO輸出1,懸空,需要外接上拉電阻,才能實現輸出高電平。當輸出爲1時,IO口的狀態由上拉電阻拉高電平,但由於是開漏輸出模式,這樣IO口也就可以由外部電路改變爲低電平或不變。可以讀IO輸入電平變化,實現C51的IO雙向功能。

(6)GPIO_Mode_Out_PP 推輓輸出—IO輸出0-接GND,IO輸出1 -接VCC,讀輸入值是未知的。

(7)GPIO_Mode_AF_OD 複用開漏輸出—片內外設功能(TX1,MOSI,MISO.SCK.SS)。

(8)GPIO_Mode_AF_PP 複用推輓輸出—片內外設功能(I2C的SCL,SDA)。
————————————————

參考鏈接:https://blog.csdn.net/santa9527/article/details/78842832

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章