woshi_ziyu
发表于: 2015-12-5 18:01:01 | 显示全部楼层

上一篇文章中,我们介绍了搭建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熄灭。


跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 48 | 回复: 79



手机版|

GMT+8, 2024-4-26 13:13 , Processed in 0.054205 second(s), 7 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表