STM32L0XX_HAL_GPIO.C
// @file stm32l0xx_hal_gpio.c
// 文件 stm32l0xx_hal_gpio.c
// @author MCD Application Team
// 作者 MCD应用团队
// @brief GPIO HAL module driver.
// 简明的 GPIO HAL 模块驱动
// This fiel provides firmware functions to manage the following functionalities
// of the General Purpose Input/Output(GPIO) peripheral:
// 这个文件提供了管理通用输入/输出GPIO外设的固件函数
// 初始化和反初始化函数
// +IO operation functions
// IO操作函数
// Copyright (c) 2016 STMicroelectronics.
// 版权所有
// All rights reserved.
// 保留所有权利
// This software is licensed under terms that can be found in the LICENSE file in
// the root directory of this software component.
// 本软件是根据本软件组件根目录的LICENSE文件中的条款获得许可的。
// If no LICENSE file comes with this software,it is provided AS-IS.
// 如果此软件未附带许可证文件,则按原样提供。
// GPIO Peripheral features
// GPIO外设功能 (特征 特色 特点 ; 以...为特色)
// Each port bit of the general-purpose IO (GPIO) ports can be individually configured
// by software in several modes:
// 通用IO(GPIO)端口的每个端口位可以通过软件以下面的模式单独配置:
// Input mode
// 输入模式
// Analog mode
// 模式模式
// Output mode
// 输出模式
// Alternate function mode
// 复用功能模式
// External interrupt/event lines
// 外部中断/事件线
// During and just after reset,the alternate functions and external interrupt lines are not
// active and the IO ports are configured in input floating mode.
// 在重置期间或重置后,备用功能和外设中断线不起作用并且IO端口被配置为输入浮空模式。
// All GPIO pins have weak internal pull-up and pull-down resistors,which can be activated or not.
// 所有GPIO引脚都有弱的内部上拉和下拉电阻器,可以选择激活或者不激活。
// In Output or Alternate mode ,each IO can be configured on open-drain or push-pull type and the IO
// speed can be selected depending on the VDD value.
// 在输出或者复用模式下,每个IO可以配置为开漏或者推完模式,IO速度可以根据VDD值进行选择。
// The microcontroller IO pins are connected to onboard peripherals/modules through a multiplexer that
// allows only one peripheral alternate function (AF) connected to an IO pin at a time.In this way,there
// can be no conflict betewwn peripherals sharing the same IO pin.
// 微控制器IO引脚通过多路复用器链接到板载外设,一次只允许一个外设复用功能启用,通过这种共享同一IO引脚的两个外设
// 之间不会发生冲突。
// All ports have external interrupt/event capability.To use external interrupt lines,the port must be
// configured in input mode.All available GPIO pins are connected to the 16 external interrupt/event lines
// from EXTI0 to EXTI15.
// 所有的端口都具有外部中断/事件能力。要使用外部中断线,端口必须配置为输入模式。所有可用的GPIO引脚都链接到16条外部中断/
// 时间线,从EXTI0到EXTI15。
// The external interrupt/event controller consists of up to 28 edge detectors (16 lines are connected to GPIO)
// for generating event/interrupt requests each input line can be independently configured to select the type)
// (interrupt or event) and the corresponding trigger event (rising or falling or both).Each lines can also
// be masked independently.
// 外部中断/事件控制器由多大28个边缘检测器组成,(16条线路连接到GPIO),用于生成中断/事件请求(每条输入线可以独立配置以选择
// 类型(中断或事件)以及相应的触发事件(上升或下降或两者)。每条线都可以被独立的屏蔽。
// How to use this driver
// Enable the GPIO IOPORT clock using the following function :__HAL_RCC_GPIOx_CLK_ENABLE().
// 使用以下函数启用GPIO IOPORT时钟
// Configure the GPIO pin(s) using HAL_GPIO_Init().
// 使用HAL_GPIO_Init()配置GPIO引脚
// Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
// 使用GPIO_InitTypeDef结构中的"mode"成员配置IO模式
// Activate Pull-up,Pull-down resistor using "Pull" member from GPIO_InitTypeDef structure
// 使用GPIO_Init_TypeDef结构中的"pull"成员激活上拉、下拉电阻器
// resistor:电阻器
// In case of Output or alternate function mode selection: the speed is configured through "Speed"
// member from GPIO_InitTypeDef structure.
// 在选择输出或复用功能模式的情况下:可以使用GPIO_InitTypeDef结构中的速度成员。
// In alternate mode is selection,the alternate function connected to the IO is configured through
// "Alternate" member from GPIO_InitTypeDef structure.
// 在选择复用功能时,通过GPIO_InitTypeDef结构体中的“复用”成员配置连接到IO的复用功能。
// Analog mode is required when a pin is to be used as ADC channel or DAC output.
// 当引脚用作ADC通道或DAC输出时,需要使用模拟模式。
// In case of external interrupt/event selection the "Mode" member from GPIO_InitTypeDef structure select
// the type (interrupt or event) and the corresponding trigger event (rising or falling or both).
// 在外部中断/事件模式的情况下,GPIO_InitTypeDef结构体中的"模式"成员选择类型(中断/事件)和相应的触发事件(上升或
// 下降或两者兼有)。
// In case of external interrupt/event mode selection, configure NVIC IRQ priority mapped to the EXTI line unsing
// HAL_NVIC_SetPriority() and enable it using HAL_NVIC_EnableIRQ.
// 在外部中断/事件模式选择下,配置映射到EXIT线路的NVIC IRQ优先级可以使用HAL_NVIC_SetPriority()并使用HAL_NVIC_EnableIRQ
// 启用它。
// HAL_GPIO_DeInit allows to set register values to their reset value.This function is also to be used when unconfiguring
// pin which was used as an external interrupt or in event mode.That is the only way to reset the corresponding bit in
// EXIT & SYSCFG registers.
// HAL_GPIO_DeInit允许将寄存器值设置为其重置值。当取消对用作外部中断或事件模式的引脚的配置时,也可以使用此功能。这是重置EXIT和SYSCFG
// 寄存器中的响应位。
// To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
// 要获得在输入模式下配置的引脚的电平,请使用HAL_GPIO_ReadPin()函数。
// To set/reset the level of a pin configured in output mode use HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
// 要置位/复位在输出模式下配置的引脚的电平,请使用HAL_GPIO_WritePin()/HAL_GPIO_TogglePin()这两个函数。
// To lock pin configuration until next reset use HAL_GPIO_LockPin().
// 要锁定引脚配置直到下一次重置,请使用HAL_GPIO_LockPin()函数。
// During and just afer reset.the alternate functions are not activ and the GPIO pins are configured in input floating mode(except JTAG
// pins).
// 重置期间或之后,复用功能不起作用,GPIO引脚配置为输入浮空模式(JTAG引脚除外)。
// The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose(PC14 and PC15,respectively) when the LSE oscillator is
// off.The LSE has priority over the GPIO function.
// 当LSE振荡器关闭时,LSE振荡器引脚OSC32_IN and OSC32_OUT可以用作通用GPIO(PC14和PC15)。LSE优先于GPIO功能。
// The HSE oscillator pins OSC_IN/OSC_OUT can be used as general purpose PH0 and PH1,respectively,when the HSE oscillator is off.
// The HSE has priority over the GPIO function.
// 当HSE 振荡器关闭时,HSE震荡器引脚OSC_IN/OSC_OUT可以分别用作通用PH0和PH1。HSE优先于GPIO功能。
#include "stm32l0xx_hal.h"
#ifdef HAL_GPIO_MODULE_ENABLE
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx,GPIO_InitTypeDef *GPIO_Init)
{
uint32_t positon = 0x00U;
uint32_t iocurrent = 0x00U;
uint32_t tem = 0x00U;
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
assert_param(IS_GPIO_PIN_AVAILABLE(GPIOx,(GPIO_Init->Pin)));
// AVAILABLE:可获得的;可购得的;可找到的;有空的
while(((GPIO_Init->Pin) >> position) != 0)
// position:位置;地方;恰当位置;处境;观点;地位;角色;安装;安置
{
iocurrent = (GPIO_Init -> Pin) & (1U << positon);
// current:现在的;当前的;流通的;流行的;电流;气流;潮流
if(iocurrent)
{
//在选择输出或复用功能模式的情况下
if(((GPIO_Init -> Mode & GPIO_MODE) == MODE_OUTPUT) || ((GPIO_Init -> Mode & GPIO_MODE) == MODE_AF))
{
// 检查速度参数
assert_param(IS_GPIO_SPEED(GPIO_Init -> Speed));
// 配置IO速度
temp = GPIOx -> OSPEEDR;
temp &= ~(GPIO_OSPEEDER_OSPEED0 << (position * 2U));
// OSPEEDER:调速器
temp |= (GPIO_Init -> Speed << (positon * 2U));
GPIOx -> OSPEEDER = temp;
// 配置IO输出类型
temp = GPIOx -> OTYPER;
// OTYPER:OUT PUT TYPER
temp &= ~(GPIO_OTYPER_OT_O << position);
temp |= (((GPIO_Init -> Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << positon);
GPIOx -> OTYPER = temp;
}
if((GPIO_Init -> Mode & GPIO_MODE) != MODE_ANALOG)
{
//检查Pull参数
assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
// 激活当前IO的上下拉电阻器
temp = GPIOx -> PUPDR;
temp &= ~(GPIO_PUPDR_PUPDO << (position * 2U));
temp |= ((GPIO_Init -> Pull) << (position * 2U));
GPIOx -> PUPDR = temp;
}
// 在选择复用功能模式的情况下
if((GPIO_Init -> Mode & GPIO_MODE) == MODE_AF)
{
//检查复用功能参数
assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
// INSTANCE:实例
assert_param(IS_GPIO_AF(GPIO_Init -> Alternate));
// Alternate:候补;代理人;交替
//配置与当前IO映射的复用功能
temp = GPIOx -> AFR[position >> 3U];
temp &= ~(0xFUL << ((uint32_t)(position & 0x07UL) * 4U));
temp |= ((uint32_t) (GPIO_Init -> Alternate) << (((uint32_t) position &(uint32_t)0x07U) * 4U));
GPIOx -> AFR[position >> 3U] = temp;
// 配置IO方向模式(输入、输出、备用或模拟)
temp = GPIOx -> MODER;
temp &= ~(GPIO_MODER_MODE0 << (position * 2U));
temp |= ((GPIO_Init -> Mode & GPIO_MODE) << (position * 2U));
GPIOx -> MODER = temp;
// EXTI模式配置
// 为当前IO配置外部中断或事件
if((GPIO_Init -> Mode & EXTI_MODE) != 0x00U)
{
// 启用SYSCFG时钟
__HAL_RCC_SYSCFG_CLK_ENABLE();
temp = SYSCFG -> EXTICR[position >>2U];
CLEAR_BIT(temp,(0x0FUL) << (4U * (position & 0x03U)));
SET_BIT(temp,(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03U));
SYSCFG->EXTICR[position >> 2U] = temp;
// 清除上升下降边缘配置
temp = EXTI->RTSR;
temp &= ~((uint32_t)iocurrent);
if((GPIO_Init->Mode & TRIGGER_RISING) != 0x00U);
{
temp |= iocurrent;
}
EXTI->RTSR = temp;
temp = EXTI->FTSR;
// FTSR:下降沿触发
// RTSR:上升沿触发
temp &= !((uint32_t)iocurrent);
if((GPIO_Init->Mode & trigger_falling) != 0x00U)
{
temp |= iocurrent;
}
EXTI->FTSR = temp;
temp = EXTI->EMR;
temp &= ~((uint32_t)iocurrent);
if((GPIO_Init->Mode & EXTI_EVT) != 0x00U)
{
temp |= iocurrnet;
}
EXTI->EMR = temp;
// 清楚EXTI线路配置
temp = EXTI->IMR;
temp &= ~((uint32_t)iocurrent);
if((GPIO_Init->Mode & EXTI_IT) != 0x00U)
{
temp |= iocurrent;
}
EXTI->IMR = temp;
}
}
position++;
}
}
void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx,uint32_t GPIO_Pin)
{
uint32_t position = 0x00U;
uint32_t iocurrent = 0x00U;
uint32_t tmp = 0x00U;
// 检查参数
assert_param(IS_GPIO_PIN_AVAILABLE(GPIOx,GPIO_Pin));
// 配置端口引脚
while((GPIO_Pin >> position) != 0)
{
// 获取IO位置
iocurrent = (GPIO_Pin) & (1U << position);
if(iocurrent)
{
// EXTI模式配置
// 清楚当前IO的外部中断或事件
tmp = SYSCFG->EXTICR[position >> 2U];
tmp &= ((0x0FUL) << (4U * (position & 0x03U)));
if(tmp == (GPIO_GET_INDEX(GPIOx) << (4U * (position & 0x03U))))
{
// 清楚EXTI线路配置
EXTI->IMR &= ~((uint32_t)iocurrent);
EXTI->EMR &= ~((uint32_t)iocurrent);
// 清楚上升或下降边缘配置
EXTI->FTSR &= ~((uint32_t)iocurrent);
EXTI->RTSR &= ~((uint32_t)iocurrent);
tmp = (0x0FUL) << (4U * (position & 0x03U));
SYSCFG->EXTICR[position >> 2U] &= ~tmp;
}
// GPIO模式配置
// 在模拟模式下配置IO方向(重置状态)
GPIOx->MODER |= (GPIO_MODE_ANALOG << (position * 2U));
// 配置当前IO中的默认复用功能
GPIOx->AFR[position >> 3U] &= ~(0xFUL << ((uint32_t) (position & 0x07UL) * 4U));
// position:位置;角色;地方
// 停用当前IO的上拉和下拉电阻器
GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
// 配置默认值IO输出类型
GPIOx->otyper &= ~(GPIO_OTYPER_OT_0 << position);
// 配置IO速度的默认值
GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEED0 << (position * 2U));
}
position++;
}
}
// IO操作函数
// 读取指定的输入端口引脚
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)
{
GPIO_PinState bitstatus;
// 检查参数
assert_param(IS_GPIO_PIN_AVAILABLE(GPIOx,GPIO_Pin));
if((GPIOx->IDR & GPIO_Pin) != (uint32_t)(GPIO_PIN_RESET))
{
bitstatus = GPIO_PIN_SET;
} else
{
bitstatus = GPIO_PIN_RESET;
}
return bitstatus;
}
// 设置或清除选定的数据端口位
// This function uses GPIOx_BSRR register to allow atomic read/modify accesses.In this way, there is no
// risk of an IRQ occurring between the read and the modify access.
// 此函数使用GPIOx_BSRR寄存器来允许原子读取/修改访问。通过这种方式,在读取和修改访问之间不存在发生IRQ的风险。
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState)
{
// 检查参数
assert_param(IS_GPIO_PIN_AVAILABLE(GPIOx,GPIO_Pin));
assert_param(IS_GPIO_PIN_ACTION(PinState));
if(PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BRR = GPIO_Pin;
}
}
// 切换指定的GPIO引脚
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)
{
uint32_t odr;
// 检查参数
assert_param(IS_GPIO_PIN_AVAILABLE(GPIOx,GPIO_Pin));
// 获取当前输出数据寄存器值
odr = GPIOx->ODR;
// 设置低电平的选定引脚,并重置高电平的引脚
GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
}
// 锁定GPIO引脚配置寄存器
HAL_StartusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
{
__IO uint32_t tmp = GPIO_LCKR_LCKK;
// 检查参数
assert_param(IS_GPIO_PIN_AVAILABLE(GPIOx,GPIO_Pin));
// 应用锁定键写入顺序
tmp |= GPIO_Pin;
// 设置LCK
GPIOx->LCKR = tmp;
// 复位LCK
GPIOx->LCKR = GPIO_Pin;
// 设置LCK
GPIOx->LCKR = tmp;
读取LCKK寄存器,此读书是完成钥匙锁定顺序所必须的。
tmp = GPIOx->LCKR;
// 再次读取以确认锁定处于活动状态
if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET)
{
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
// 此函数处理EXTI中断请求
// GPIO_Pin指定连接到EXTI线的引脚
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
// 检测到EXTI线路中断
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
// EXTI线路检测回调
// GPIO_Pin指定连接到EXTI线的引脚
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
// 阻止未使用的参数编译警告
UNUSED(GPIO_Pin);
// 注意:不应该修改此函数,当需要回调时,可以在用户文件中实现 HAL_GPIO_EXTI_Callback
}
07-05
03-25
14万+
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountBlack.png)
03-07
1445
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountBlack.png)