【STM32H7教程】第17章 STM32H7之GPIO的HAL库API

发布者:EnchantedWish最新更新时间:2019-08-27 来源: eefocus关键字:STM32H7  GPIO  HAL库  API 手机看文章 扫描二维码
随时随地手机看文章

17.1 初学者重要提示

1、  如何阅读HAL库源码的问题


HAL库实现的函数有复杂的,也有简单的,简单的可以直接阅读代码。复杂的代码阅读起来比较耗时间,如果再配合参考手册抠每个寄存器的配置,那就更消耗时间了。所以对于这种函数,用户仅需了解每个部分实行的功能即可,而且HAL库都做了关键注释,以说明这部分实现的功能。所以用户没有必要去抠每个配置是如何实现的,仅需知道实现了什么功能。以后工程项目有需要了解具体配置时,再看即可。


2、  学习本章节前,务必保证已经学习了第15章。


17.2 GPIO涉及到的寄存器

GPIO外设涉及到的寄存器比较少,也容易理解,推荐大家阅读GPIO源码的时候将参考手册中对应的寄存器功能做一个了解。


很多时候,我们会直接调用GPIO的寄存器进行配置,而不使用HAL进行调用,以提高执行效率,特别是中断里面执行时。


17.3 源文件stm32h7xx_hal_gpio.c

这个文件主要是实现GPIO的引脚配置,学习这个文件注意事项:


  系统上电后,引脚默认状态是模拟模式。

  所有的引脚有弱上拉和弱下拉电阻,阻值范围30-50KΩ。其中配置为模拟模式时,上拉和下拉被硬件禁止,其它的输入、输出和复用都可以配置上拉和下拉。

  在输出或者复用模式,每个引脚可以配置成推挽或者开漏,且有GPIO速度等级可配置。另外注意,不同的供电范围,实际速度等级是有些区别的。

  每个GPIO都可以配置成外部中断/事件模式,但要特别注意,引脚要配置成输入模式,在芯片的内部有个多路选择器,选择引脚与16个外部中断/事件EXTI0 - EXTI15中的那个导通。这就决定了,每个外部中断/事件只能与一个引脚导通,如果用户配置了多个引脚PA0,PB0,PC0等,那么只有一个能够与EXTI0导通。

17.3.1 函数HAL_GPIO_Init

函数原型:


void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)

{

/* 部分省略未写 */

 

  /* 配置GPIO引脚,这些采用16个引脚的循环检测模式 */

  for(position = 0; position < GPIO_NUMBER; position++)

  {

     /* 部分省略未写 */

    if(iocurrent == ioposition)

    {

      /*--------------------- GPIO模式配置 ------------------------*/

     

      /*--------------------- EXTI模式配置 ------------------------*/

     

    }

  }

}

函数描述:


此函数用于初始化GPIO,此函数主要实现如下功能:


  GPIO功能配置。

  设置EXTI功能。

函数参数:


  第1个参数用于填写使用的端口号,可以是:

#define GPIOA    ((GPIO_TypeDef *) GPIOA_BASE)

#define GPIOB    ((GPIO_TypeDef *) GPIOB_BASE)

#define GPIOC    ((GPIO_TypeDef *) GPIOC_BASE)

#define GPIOD    ((GPIO_TypeDef *) GPIOD_BASE)

#define GPIOE     ((GPIO_TypeDef *) GPIOE_BASE)

#define GPIOF     ((GPIO_TypeDef *) GPIOF_BASE)

#define GPIOG     ((GPIO_TypeDef *) GPIOG_BASE)

#define GPIOH     ((GPIO_TypeDef *) GPIOH_BASE)

#define GPIOI      ((GPIO_TypeDef *) GPIOI_BASE)

#define GPIOJ      ((GPIO_TypeDef *) GPIOJ_BASE)

#define GPIOK     ((GPIO_TypeDef *) GPIOK_BASE)

  第2个形参是GPIO_InitTypeDef类型的结构体变量,这个变量比较重要,要熟练掌握,定义如下:

typedef struct

{

  uint32_t Pin;    

  uint32_t Mode; 

  uint32_t Pull;     

  uint32_t Speed;   

  uint32_t Alternate; 

}GPIO_InitTypeDef;

下面将结构体每个成员做个说明:


  成员Pin用于配置选择的引脚,范围GPIO_PIN_0到GPIO_PIN_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_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速度等级,有下面四种可选:

GPIO_SPEED_FREQ_LOW          /* 低速 */

GPIO_SPEED_FREQ_MEDIUM      /* 中等速度 */

GPIO_SPEED_FREQ_HIGH         /* 快速 */

GPIO_SPEED_FREQ_VERY_HIGH   /* 高速  */

  成员Alternate用于配置引脚复用,可选择的复用方式在文件stm32h7xx_hal_gpio_ex.h里面进行了定义,比如串口复用:

GPIO_AF7_USART1   

GPIO_AF7_USART2    

GPIO_AF7_USART3       

GPIO_AF7_USART6    

GPIO_AF7_UART7 

注意事项:


与F1,F4系列的标准库不同,H7的HAL库已经没有单独的EXTI外部中断设置文件,是将其整合到此函数里面了。

函数HAL_GPIO_Init对引脚的初始化是把同组16个引脚for循环检测了一遍,效率稍低。所以不推荐下面这种初始化:

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;                   

GPIO_InitStruct.Pull = GPIO_NOPULL;              

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;  

GPIO_InitStruct.Pin = GPIO_PIN_0;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);   //这里会执行16次for查询

 

GPIO_InitStruct.Pin = GPIO_PIN_1;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);   //这里会执行16次for查询

       

GPIO_InitStruct.Pin = GPIO_PIN_2;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  //这里会执行16次for查询

如果是程序运行期间的引脚状态切换,最好采用下面的方式或者直接寄存器操作:


GPIO_InitStruct.Pin = GPIO_PIN_0 |GPIO_PIN_1 | GPIO_PIN_2 ;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;                   

GPIO_InitStruct.Pull = GPIO_NOPULL;              

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;  

 

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  //这里会执行16次for查询

使用举例:


GPIO_InitTypeDef  GPIO_InitStruct;

 

GPIO_InitStruct.Pin = GPIO_PIN_0;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;      /* 推挽输出 */         

GPIO_InitStruct.Pull = GPIO_NOPULL;                /* 无上拉和下拉电阻 */ 

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* GPIO速度等级最高 */

 

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  

17.3.2 函数HAL_GPIO_DeInit

函数原型:


void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)

{  

  for(position = 0; position < GPIO_NUMBER; position++)

  {

     /* 部分省略未写 */

    if(iocurrent == ioposition)

    {

      /*------------------------- GPIO Mode Configuration --------------------*/

      /* 配置为模拟模式 */

      GPIOx->MODER |= (GPIO_MODER_MODER0 << (position * 2));

 

      /* 配置复用模式为AF0,即作为通用IO */

      GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;

 

      /* 配置到最低速度 */

      GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2));

 

      /* 输出类型是推挽,如果IO模式被设置为模拟,此选项对其没有影响 */

      GPIOx->OTYPER  &= ~(GPIO_OTYPER_OT_0 << position) ;

 

      /* 无上拉和下拉电阻 */

      GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));

 

      /*------------------------- EXTI模式配置 --------------------*/

      

    }

  }

}

函数描述:


此函数用于复位IO到初始化状态,具体状态看函数原型中的注释即可。


函数参数:


  第1个参数用于填写使用的端口号,可以是:

#define GPIOA    ((GPIO_TypeDef *) GPIOA_BASE)

#define GPIOB    ((GPIO_TypeDef *) GPIOB_BASE)

#define GPIOC    ((GPIO_TypeDef *) GPIOC_BASE)

#define GPIOD    ((GPIO_TypeDef *) GPIOD_BASE)

#define GPIOE     ((GPIO_TypeDef *) GPIOE_BASE)

#define GPIOF     ((GPIO_TypeDef *) GPIOF_BASE)

#define GPIOG     ((GPIO_TypeDef *) GPIOG_BASE)

#define GPIOH     ((GPIO_TypeDef *) GPIOH_BASE)

#define GPIOI      ((GPIO_TypeDef *) GPIOI_BASE)

#define GPIOJ      ((GPIO_TypeDef *) GPIOJ_BASE)

#define GPIOK     ((GPIO_TypeDef *) GPIOK_BASE)

  第2个参数是配置选择的引脚,范围GPIO_PIN_0到GPIO_PIN_15。

使用举例:


此函数的使用比较简单,需要调用的时候直接调用即可。


17.3.3 函数HAL_GPIO_ReadPin

函数原型:


GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

{

  GPIO_PinState bitstatus;

 

  /* Check the parameters */

  assert_param(IS_GPIO_PIN(GPIO_Pin));

 

  if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)

  {

    bitstatus = GPIO_PIN_SET;

  }

  else

  {

    bitstatus = GPIO_PIN_RESET;

  }

  return bitstatus;

}

函数描述:


此函数用于读取引脚状态,通过GPIO的IDR寄存器读取。


函数参数:


  第1个参数用于填写使用的端口号,从GPIOA到GPIAK。

  第2个参数是配置选择的引脚,范围GPIO_PIN_0到GPIO_PIN_15。

使用举例:


此函数的使用比较简单,需要调用的时候直接调用即可。


17.3.4 函数HAL_GPIO_WritePin

函数原型:


void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)

{

  /* Check the parameters */

  assert_param(IS_GPIO_PIN(GPIO_Pin));

  assert_param(IS_GPIO_PIN_ACTION(PinState));

 

  if(PinState != GPIO_PIN_RESET)

  {

    GPIOx->BSRRL = GPIO_Pin;

  }

  else

  {

    GPIOx->BSRRH = GPIO_Pin ;

  }

}

函数描述:


此函数用于设置引脚输出高电平或者低电平。使用GPIO的BSRR寄存器进行设置,使用这个寄存器的好处是支持原子操作,由硬件支持的。原子操作的含义是操作过程不会被中断打断,而我们使用GPIO中另一个设置输出的寄存ODR是会被中断打断的。大家看下寄存器赋值操作对应的反汇编,是由多条汇编指令组成的。


函数参数:


  第1个参数用于填写使用的端口号,从GPIOA到GPIAK。

  第2个参数是配置选择的引脚,范围GPIO_PIN_0到GPIO_PIN_15。

  第3个参数用于设置引脚输出高电平还是低电平,GPIO_PIN_RESET表示低电平,GPIO_PIN_SET表示高电平。

使用举例:


此函数的使用比较简单,需要调用的时候直接调用即可。


17.3.5 函数HAL_GPIO_TogglePin

函数原型:


void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

{

  /* Check the parameters */

  assert_param(IS_GPIO_PIN(GPIO_Pin));

 

  GPIOx->ODR ^= GPIO_Pin;

}

函数描述:


此函数用于设置引脚的电平翻转,使用GPIO的ODR寄存器进行设置。


函数参数:


  第1个参数用于填写使用的端口号,从GPIOA到GPIAK。

  第2个参数是配置选择的引脚,范围GPIO_PIN_0到GPIO_PIN_15。

使用举例:


此函数的使用比较简单,需要调用的时候直接调用即可。


17.3.6 函数HAL_GPIO_LockPin

函数原型:


HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

{

  __IO uint32_t tmp = GPIO_LCKR_LCKK;

 

  assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));

  assert_param(IS_GPIO_PIN(GPIO_Pin));

 

  /* 应用IO锁的写入顺序 */

  tmp |= GPIO_Pin;

  /* 设置 LCKx bit(s): LCKK='1' + LCK[15-0] */

  GPIOx->LCKR = tmp;

  /* 复位 LCKx bit(s): LCKK='0' + LCK[15-0] */

  GPIOx->LCKR = GPIO_Pin;

  /* 设置 LCKx bit(s): LCKK='1' + LCK[15-0] */

  GPIOx->LCKR = tmp;

  /* 复位 LCKK bit*/

  tmp = GPIOx->LCKR;

 

 if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET)

  {

    return HAL_OK;

[1] [2]
关键字:STM32H7  GPIO  HAL库  API 引用地址:【STM32H7教程】第17章 STM32H7之GPIO的HAL库API

上一篇:【STM32H7教程】第18章 STM32H7的GPIO应用之跑马灯
下一篇:【STM32H7教程】第16章 STM32H7必备的HAL库API(重要)

推荐阅读最新更新时间:2024-10-29 19:06

STM32 - GPIO 的位带操作
我采用得是STM32F10RC 参考得是STM32普中科技的给出得例子:https://www.bilibili.com/video/av30149282/?p=45(这里给出网址) https://blog.csdn.net/bulebin/article/details/73730141 这个博文还可以 ps:在15中 是个hi用sbit 进行位带 1、位带介绍 什么是位带呢? stm32 中没有sbit, 所以我们采用的是位带别名区 (1) 通过访问Bit band Alias 他 来控制 bit Band ALias 的位 (2)位带区和位带别名区的转换 别名区地址=外设微带别名区的基地址
[单片机]
STM32 - <font color='red'>GPIO</font> 的位带操作
MCF51QEl28快速GPIO的外部总线接口设计
引言 外部总线接口大都出现在功能和价格较高的高端微处理器中。例如,Freescale半导体公司生产的Coldfire和PowerPC微处理器,在低端的微控制器行列中,一般很少出现,主要原因是微控制器一般内部包含了Flash和SRAM,而不是像微处理器那样需要外扩大容量存储器放置代码和运行程序。但是,微控制器也会遇到需要外扩外部总线设备的情况,笔者在某项目中需要使用McF51QEl28(以下简称“QEl28”)微控制器连接外部Flash存储测试数据,存取速度要求较高,因此无法使用串行接口的存储器,只能使用具有地址线和数据线的Flash存储器。 QEl28是Freescale半导体公司推出的Flexis系列的首款产品,具有25
[工业控制]
MCF51QEl28快速<font color='red'>GPIO</font>的外部总线接口设计
STM8配置GPIO输入输出功能
1.GPIO工作模式 输入: 浮空输入 上拉输入 输出: 推挽输出 开漏输出 (1).浮空输入:浮空输入,可以做KEY识别,RX1 (2).带上拉输入:IO内部上拉电阻输入 (3).开漏输出:IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。 (4).推挽输出:IO输出0-接GND,IO输出1 -接VCC,读输入值是未知的 2.软件配置 参考:STM8S中文书据手册、原理图、google 初始化流程: cpu时钟初始化 IO
[单片机]
S3C2440 GPIO (使用miniARM 2440)
S3C2440 GPIO (使用miniARM 2440): #ifndef LDE_H #define LED_H #include 2440addr.h //GPB 有 PIN0 到 PIN10 共11个引脚 //rGPBCON 寄存器的每两个位控制一个IO的输入输出方向 //其中00表示输入 // 01表示输出 // 10为使用第二功能 // 11为出厂保留 //*************************************************** //功能:流水灯 //接口: GPB5 - LED1 低 灯亮
[单片机]
stm32 GPIO简单介绍及初始化配置(库函数)
前言: 相信,大部分查找GPIO的人,都是刚刚接触STM32的人,而刚接触STM32的人,大部分是从51上来的人,所以我会由浅入深,从51和STM32的区别入手,通过对比这两个处理器的配置方法,来跟大家慢慢讲解(学知识可不能急于求成)。博主以stm32f1为主控芯片,以下均简称为stm32。 首先,上一张我的理解图(画不好。。。但能看),给个形象的概念 一、讲图之前,先给大家一个stm32的概念:“时钟概念” 1. STM32的时钟是什么? stm32的时钟是由内部或外部振荡器产生的“频率”,而被人们形象的称为“系统时钟”。最大为72MHz换成周期T为:1/72MHz≈13.9ns 2. 为什么要用时钟? 因为耗电量,s
[单片机]
stm32实现GPIO输入按键检测
1、硬件设计 按键机械触点断开、闭合时,由于按键触点的弹性作用,按键开关不会马上稳定接通或一下就断开,使用按键时就会产生下图中的带纹波信号,需要软件消抖处理滤波 由于用软件消抖处理滤波不方便输入检测,所以提出了如下带有硬件消抖的电路。 从按键的原理图可知,当按键没有被按下时,GPIO引脚通过一个下拉电阻R64使引脚处于低电平状态,当按键被按下时,按键所在的电路导通,VCC通过一个限流电阻R33连接到GPIO引脚,使GPIO引脚的输入状态为高电平,只要我们检测引脚的输入电平为高电平,即可判断按键是否被按下。 同LED工程,为了使工程的移植性更高,是工程更有条理,我们把按键相关的代码独立分开存储,在工程模板
[单片机]
stm32实现<font color='red'>GPIO</font>输入按键检测
STM32系列第3篇--GPIO初始化
使能和初始化IO口: GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOD,
[单片机]
ST新娃STM32H7出世 直击物联时代
政府说,在这个变化万千的多元时代,一个娃怎么够? ST果断积极响应政府鼓励生二胎政策,继STM32F7,ST强势推出了400MHz基于Cortex-M7的微处理器STM32H7,它的一系列配置也是直接面向物联网时代的应用设计需求,可谓为物联网而生。 图示1 STM32F7和家族其他宝宝与 STM32H7 那么,一起看看ST为他们的新娃STM32H7做了哪些的赶时代潮流的装备。 基础指标 :首款采用40nm嵌入式闪存技术,CoreMask测试2010分 STM32 F7采用了ST 90nm嵌入式闪存技术,CoreMask测试1000分,而STM32 H7的在400M
[单片机]
ST新娃<font color='red'>STM32H7</font>出世 直击物联时代
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved