本文可能含有一些读者未曾掌握的知识点在内,其存在只是为了让笔者能够正常进行讲述,而不至于一直用类似于“什么什么之类的”这种无用的废话来浪费读者的时间。
所以如果有的名词读者看不懂,别担心,随便看看也好嘛
我该去哪里找到这些函数?
首先最直观的当然就是ST的HAL库官方手册啦。
不过这本手册的内容只是函数声明的简单堆叠,因此建议去看看HAL库的函数源码中的注释。我们来举个简单的小例子:
/**
******************************************************************************
* @file stm32f4xx_hal_gpio.c
* @author MCD Application Team
* @brief GPIO HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the General Purpose Input/Output (GPIO) peripheral:
* + Initialization and de-initialization functions
* + IO operation functions
*
@verbatim
==============================================================================
##### GPIO Peripheral features #####
==============================================================================
[..]
Subject to the specific hardware characteristics of each I/O port listed in the datasheet, each port bit of the General Purpose IO (GPIO) Ports, can be individually configured by software in several modes:
(+) 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 I/O ports are configured in input floating mode.
[..]
All GPIO pins have weak internal pull-up and pull-down resistors, which can be activated or not.
[..]
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.
[..]
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.
[..]
The external interrupt/event controller consists of up to 23 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 line can also be masked independently.
##### How to use this driver #####
==============================================================================
[..]
(#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
(#) Configure the GPIO pin(s) using HAL_GPIO_Init().
(++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
(++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef structure.
(++) In case of Output or alternate function mode selection: the speed is configured through "Speed" member from GPIO_InitTypeDef structure.
(++) In alternate mode is selection, the alternate function connected to the IO is configured through "Alternate" member from GPIO_InitTypeDef structure.
(++) Analog mode is required when a pin is to be used as ADC channel or DAC output.
(++) 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).
(#) In case of external interrupt/event mode selection, configure NVIC IRQ priority mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using HAL_NVIC_EnableIRQ().
(#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
(#) To set/reset the level of a pin configured in output mode use HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
(#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
(#) During and just after reset, the alternate functions are not active and the GPIO pins are configured in input floating mode (except JTAG pins).
(#) 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.
(#) 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.
@endverbatim
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2017 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
这大段的注释出现在stm32f4xx_hal_gpio.c中,整体上先是介绍了GPIO的外设特点(模式、内部上下拉、中断等),接着介绍了如何使用GPIO的驱动(驱动GPIO的流程):
使能总线时钟→引脚初始化→(配置中断→设置优先级→)获取/配置引脚状态
以上内容可以说是相当的详细了,在使用的过程中会对我们有很大的帮助。
同时不只是对于整个模块有详细的介绍,对于每个函数也都有注释做详细的介绍,例如对于HAL_GPIO_WritePin函数就有如下的详细介绍:
/**
* @brief Sets or clears the selected data port bit.
*
* @note 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.
*
* @param GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
* x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
* @param GPIO_Pin specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* @param PinState specifies the value to be written to the selected bit.
* This parameter can be one of the GPIO_PinState enum values:
* @arg GPIO_PIN_RESET: to clear the port pin
* @arg GPIO_PIN_SET: to set the port pin
* @retval None
*/
关于注释的内容:
详细内容可以参考这篇文章,这里简单介绍下:
brief:函数功能简介
note:函数使用过程中需要注意的事项
param:即parameter,函数中的参数相关说明
retval:即return value,函数返回值
大致看了看注释,是不是对于函数有更深的了解了呢?现在我们可以开始大规模复制粘贴真正的主题了。
GPIO函数
GPIO写函数:配置GPIO引脚状态
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->BSRR = GPIO_Pin;//将BSRR寄存器置位,进而完成引脚的配置
}
else
{
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
}
}
使用示例:
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);//将PC13置高
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);//将PC13置低
GPIO读函数:读取GPIO引脚状态并返回对应的状态值
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_PinState bitstatus;
//断言验证参数正确性
assert_param(IS_GPIO_PIN(GPIO_Pin));
//读取IDR寄存器的对应引脚位
if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
{
//若为高,返回GPIO_PIN_SET
bitstatus = GPIO_PIN_SET;
}
else
{
//否则,返回GPIO_PIN_RESET
bitstatus = GPIO_PIN_RESET;
}
return bitstatus;
}
使用示例:
//判断PA0是否为高电平
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
//如果是,将PC13置高
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
} else {
//如果不是,将PC13置低
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
}
GPIO翻转引脚状态:反转GPIO引脚的状态
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint32_t odr;
//断言验证参数正确性
assert_param(IS_GPIO_PIN(GPIO_Pin));
//读取ODR寄存器的值
odr = GPIOx->ODR;
//通过写入BSRR寄存器更改引脚状态
GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
}
使用示例:
//判断A0的状态是否为高
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET)
//如果是,反转PC13的引脚状态
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
GPIO中断回调函数:
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
//函数内容需要在用户文件中重新定义
UNUSED(GPIO_Pin);
}
使用示例:
//在用户文件中定义函数:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
//当中断触发的时候反转PC13引脚的状态
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}
篇幅限制,只能讲这么多了,剩下的我们下一篇文章再看。