2016年2月14日星期日

【NUCLEO-L476RG学习笔记】基于HAL库的GPIO例程介绍

上一篇文章中,我们介绍了搭建Keil开发环境,并建立了第一个LED例程。现在我们来看看这个例程是怎么工作的。

根据NUCLEO-L476RG的原理图,可以看出LD2二极管连接到PA5,USER按键连接到PC13。
使用GPIO的第一步时使能时钟。该功能通过RCC(Reset and clock control)寄存器控制。所有的GPIO连接到AHB2总线。HAL库提供了专门的函数来启用GPIOA的时钟:
  1. __HAL_RCC_GPIOA_CLK_ENABLE
复制代码
该函数定义可在文件stm32l4xx_hal_rcc.h找到,其实现函数如下:
  1. #define __HAL_RCC_GPIOA_CLK_ENABLE()           do { \
  2.                                                        __IO uint32_t tmpreg; \
  3.                                                       SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \
  4.                                                      /* Delay after an RCC peripheral clock enabling */ \
  5.                                                      tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \
  6.                                                      UNUSED(tmpreg); \
  7.                                                      } while(0)
复制代码
通过实现函数可知,主要方式是通过RCC_AHB2ENR寄存器的第0位(GPIOA EN)置位来实现。

接下来我们需要定义一个GPIO_InitTypeDef结构体来设置GPIO的参数设置。
  1. GPIO_InitTypeDef  GPIO_InitStruct;
复制代码
该结构体有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

HAL库提供了GPIO的初始化函数HAL_GPIO_Init()。该函数声明位于stm32l4xx_hal_gpio.h文件中。
  1. void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
复制代码
我们需要将连接LD2的引脚PA5设置成推挽输出模式、带上拉电阻和输出频率最大为80MHz。具体代码如下:
  1. GPIO_InitTypeDef  GPIO_InitStruct;

  2. __HAL_RCC_GPIOA_CLK_ENABLE();

  3. GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
  4. GPIO_InitStruct.Pull  = GPIO_PULLUP;
  5. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  6. GPIO_InitStruct.Pin = GPIO_PIN_5;
  7. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
复制代码
这样Led的配置就算完成了。我们可以使用以下代码点亮该Led:
  1. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
复制代码
使用以下代码熄灭Led灯:
  1. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
复制代码
也可以实现闪烁Led的效果:
  1. HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
复制代码

现在我们来设置USER按键。根据上面的藐视,我们需要将USER用户按钮设置成悬浮输入模式、带上拉和最大输出80MHz。代码如下:
  1. __HAL_RCC_GPIOC_CLK_ENABLE();

  2. GPIO_InitDef.Pin = GPIO_PIN_13;
  3. GPIO_InitDef.Mode = GPIO_MODE_INPUT;
  4. GPIO_InitDef.Pull = GPIO_PULLUP;
  5. GPIO_InitDef.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  6. //Initialize pins
  7. HAL_GPIO_Init(GPIOC, &GPIO_InitDef);
复制代码
我们可以使用以下函数来读取输入引脚的当前状态:
  1. HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13))
复制代码
以下是程序所有的代码:
  1. #include "stm32l4xx.h"
  2. #include "stm32l4xx_hal_rcc.h"
  3. #include "stm32l4xx_hal_gpio.h"

  4. int main(void) {
  5.         GPIO_InitTypeDef GPIO_InitDef;
  6.         
  7.         __HAL_RCC_GPIOA_CLK_ENABLE();

  8.         GPIO_InitDef.Pin = GPIO_PIN_5;
  9.         GPIO_InitDef.Mode = GPIO_MODE_OUTPUT_PP;
  10.         GPIO_InitDef.Pull = GPIO_NOPULL;
  11.         GPIO_InitDef.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  12.         //Initialize pins
  13.         HAL_GPIO_Init(GPIOA, &GPIO_InitDef);

  14.         __HAL_RCC_GPIOC_CLK_ENABLE();

  15.         GPIO_InitDef.Pin = GPIO_PIN_13;
  16.         GPIO_InitDef.Mode = GPIO_MODE_INPUT;
  17.         GPIO_InitDef.Pull = GPIO_PULLDOWN;
  18.         GPIO_InitDef.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  19.         //Initialize pins
  20.         HAL_GPIO_Init(GPIOC, &GPIO_InitDef);

  21.         while (1) {
  22.             if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)) {
  23.                     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
  24.             } else {
  25.                     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  26.             }
  27.     }
  28. }
复制代码
下载到NUCLEO-L476开发板。开发板上的LD2点亮。当按下蓝色的USER按键时,LD2熄灭。

没有评论:

发表评论